---
title: "Rails 部署實踐 - 上傳容器鏡像"
date: 2022-03-04T00:00:00+08:00
publishDate: 2022-03-04T00:00:00Z
lastmod: 2023-09-03T17:41:34+08:00
tags: ["Rails","教學","部署","實作","Rails 部署實踐","容器","Docker"]
series: "rails-deployment-in-practice"
toc: true
permalink: "https://blog.aotoki.me/posts/2022/03/04/rails-deployment-in-practice-upload-image/"
language: "zh-tw"
---


在 [Rails 部署實踐 - 容器化 Rails 專案概述](https://blog.aotoki.me/posts/2022/02/25/rails-deployment-in-practice-rails-containerize-basic/)中，我們快速的介紹了將專案容器化的入門技巧，雖然我們可以製作出能夠運行的鏡像，卻沒辦法將它傳送到我們想要部署的環境中。

這篇文章會向大家介紹如何讓我們的伺服器可以獲取要部署的鏡像，並且加以部署。

<!--more-->

## Registry 伺服器{#registry-server}

Registry 伺服器是一種可以提供我們分發（Distribute）鏡像的伺服器，在使用 Docker 的狀況下預設會使用 Docker 的 Registry 伺服器，也是大多數專案預設採用的情況。

因為 Docker 的 Registry 伺服器是開放原始碼的，也因此我們可以自行架設，或者使用相容的伺服器來提供服務。

以下是常見的 Docker Registry 服務：

| 名稱                   | 收費         | 說明                                                       |
| ---------------------- | ------------ | ---------------------------------------------------------- |
| Docker Hub             | 私有鏡像收費 | 早期最主流的選項，因為有收費跟限流限制，通常開源專案會採用 |
| AWS ECR                | 是           | 有基本免費額度，部署到 AWS 時通常會採用                    |
| GCP Container Registry | 是           | 部署到 GCP 時通常會採用                                    |
| Quay.io                | 私有鏡像收費 | RedHat 提供的服務，通常會作為 Docker Hub 的備用方案        |
| GitHub Package         | 私有鏡像收費 | 比較少被使用，部分專案也會放一份在 GitHub 上               |
| GitLab Registry     | 是             | 跟 GitLab 搭配的服務，主要會跟其他 DevOps 解決方案一起使用  |

除此之外，像是 [DigitalOcean](https://m.do.co/c/55a8b594beba) 也有提供自己的 Docker Registry 服務，可以根據自己部署的雲端環境、需求來選擇適合的 Registry 伺服器。

### 登入 Registry 伺服器{#login-to-registry}

要上傳鏡像到 Registry 伺服器需要先進行登入，以 Docker Hub 為例子可以直接使用 `login` 命令。

```bash
$ docker login
```

後續會自動詢問帳號、密碼即可登入。

如果是非 Docker Hub 的 Registry 伺服器，只需要指定伺服器即可。

```bash
$ docker login quay.io
```

> 如果是私有的鏡像，則需要在需要部署的伺服器進行登入。

### 標記鏡像版本{#tag-the-image}

在上一個章節中我們使用了 `docker build -t myapp .` 命令來製作鏡像，然而 `myapp` 這個名稱並無法被 Registry 伺服器辨識出來，因此我們需要依照標準的格式 `伺服器/命名空間/專案:版本` 來取名。

以 Docker 為例子，因為預設會上傳到 Docker Hub 因此我們可以省略伺服器名稱，同時，命名空間就是我們的帳號，因此可以取名為 `aotokitsuruya/rails-demo` 這樣子，這個名字需要跟在 Registry 伺服器上登記的專案名稱相同。

```bash
$ docker tag myapp aotokitsuruya/rails-demo:v1.0.0
```

如果是其他的伺服器，只需要加上伺服器位置即可。

```bash
$ docker tag myapp quay.io/aotokitsuruya/rails-demo:v1.0.0
```

如果是最新一次的建置，可以省略版本名稱。

```bash
$ docker tag myapp aotokitsuruya/rails-demo
# 相等於
$ docker tag myapp aotokitsuruya/rails-demo:latest
```

> 我們會盡可能避免使用 `latest` 版本部署，因為很難知道對應的 Commit 或者版本，發生問題時很難進行除錯。

### 上傳鏡像{#push-image}

當我們的鏡像名稱跟 Registry 伺服器上的紀錄相同後，就可以使用 `push` 命令來將鏡像上傳。

```ruby
$ docker push aotokitsuruya/rails-demo:v1.0.0
```

如果使用其他鏡像伺服器，則加入伺服器的名稱。

```ruby
$ docker push quay.io/aotokitsuruya/rails-demo:v1.0.0
```

如此一來我們就可以在其他伺服器上下載到這些鏡像用於部署，而不需要手動上傳鏡像到每一台伺服器上。

## 手動匯入{#manual-import}

這是一個很少用的功能，大多數時候我們都會使用 Registry 伺服器為主，然而遇到沒有網路的環境時，使用手動匯入可能會是一個相對可行的折衷方案。

我們可以使用 `save` 命令，將鏡像從 Docker 裡面匯出為一個 `tar.gz` 的壓縮檔。

```bash
$ docker save myapp -o rails-demo.tar.gz
```

接下來可以透過各種方式上傳到伺服器，像是使用 `scp` 指令。

```bash
$ scp rails-demo.tar.gz rails.example.com:~/
```

當我們上傳到伺服器，可以用跟 `save` 對應的命令 `load` 來將鏡像載入到運行環境的 Docker 裡面。

```bash
$ docker load -i rails-demo.tar.gz
```

如此一來我們就可以將鏡像放到遠端的伺服器上，在大多數的情況下會建議使用 Registry 伺服器來抓取鏡像，會比這樣直接匯入還更加方便。

---

如果想在第一時間收到更新，歡迎[訂閱弦而時習之](https://mailchi.mp/aotoki/rails-deployment-in-practice)在這系列文章更新時收到通知，如果有希望了解的知識，可以利用[Rails 部署實踐回饋表單](https://us4.list-manage.com/survey?u=dd3d68032c0510041f1302539&id=f25e0dc43e&attribution=false)告訴我。

