GabrielCYOU_logo

docker-compose 一次建立多個 Container

當一次運行多個 Container 時,這個 docker-compose 就派上用場了,他可以在一個文件中定義多個 container,不論是從當前的相對目錄裡面的 Dockerfile build image,還是直接從 repository pull image 然後放在一起跑。

定義你的 Dockerfile

Dockerfile,建議在瀏覽前先知道設定單一 Container 怎麼做,看這篇:Docker container intro

這個部分很簡單,但先有一個從你的程式資料夾複製到 image 資料夾的概念,你可以整包 COPY . .,也就是從 Dockerfile 所在資料夾,複製到 image 的資料夾,只是 image 會很巨。

以下介紹幾個常用的:

  1. FROM:使用的作業系統,通常 alpine 是空間最小的(Google Artifact Repository 限制 500MB)
  2. COPY:就是把 Dockerfile 的相對位置複製到 image(這邊是 package*.json 移動到 image 最高路徑)
  3. WORKDIR:可以定義 RUN COPY CMD 在哪個 Folder 運行,但因為我只有一個階層 . 複製到 .,跳過
  4. CMD:在 Container 運行時的 command,通常就直接是你在實際 production 環境運行的時候的 command,這樣佔的資源也比較少(我使用 npm run dev 就沒辦法在 Azure B2ats_v2 的 2vCPU 1GB Ram 開起來…)
  5. EXPOSE:你的 App 會使用哪個 port,到時候要把 Container 的跟伺服器實際的 port 的連起來

我的資料階層:
My-app
app
—-route
node_modules
–Dockerfile
–compose.yaml
–package.json
–.dockerignore

FROM node:alpine
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["npm", "start"]
EXPOSE 3000

(Optional) docker-compose 製作 image

如果只是一個應用程式加上從 repository 抓其他的,這個步驟可以跳過。

compose.yaml 是截至我寫這篇時最新的用法,之前有 docker-compose.yml 之類的也可以,不過 compose.yaml 會被優先選用;另外新的版本不需要指定 version 了,他會自動選適合的 version。

先有個概念,在整個 compose 裡面會存在多個 container,這些 container 如果需要互相對話的話,只需要通過 service_name,以我的為例就是 remix://blablabla、cql://blablabla。你可以試著使用 docker exec -it container_name 進到其中一個 container 裡面使用 ping remix、ping cql 來看結果(container 裡面運行的 OS 可能需要安裝 ping)。

# compose.yaml
# 這個檔案可以直接使用 docker-compose up 執行
services:
  remix:
    image: your_docker_user/my-app
    build: .  # where to find the Dockerfile
    ports:
      - 3000:3000
    environment:  # environment variables
      # the url for scylla and database in composed network, not localhost. cql is the service name, you could try ping cql from remix container sh.
      DB_URL: cql
  cql:
    image: scylladb/scylla
    ports:
      - 9042:9042
    # https://docs.docker.com/storage/volumes/#use-a-volume-with-docker-compose
    volumes:
      - db:/var/lib/scylla  # should be where scylla store files

volumes:
  db:
# should always define a name for volume in order to use it in volumes:
docker-compose build --no-cache

不過像我這樣一個自己的一個從 Docker Hub 抓的 compose,其實不需要使用到 build 啦,只要把我的那個 push 上去,就可以在其他地方使用 docker-compose up 啟動!

使用 docker-compose up 整包啟動

在其他地方直接寫一個 compose.yaml 然後執行 docker-compose up -d。這邊就不用 build 那行了。

這些 container 如果需要互相對話的話,只需要通過 service_name,以我的為例就是 remix://blablabla、cql://blablabla,所以我在 remix 的 environment 設定 DB_URL,然後在我的 app 裡面就直接使用環境變數 DB_URL。

# compose.yaml
services:
  remix:
    image: gabrieljc/quipu
    ports:
      - 3000:3000
    environment:
      DB_URL: cql
  cql:
    image: scylladb/scylla
    ports:
      - 9042:9042
    volumes:
      - db:/var/lib/scylla

volumes:
  db:
docker-compose up -d

Docker 會為 compose.yaml 裡面你編寫的 services 各建立一個 container,也可以在 docker desktop 看到 compose 的 container 圖案變成好幾層的橘色。

自動建立的 images 是由 “foldername_servicename_serialnumber” 組成,最後的 serialnumber 在當 scale up 使用同個 image 建立多個 composed container 時很有用。

使用 docker exec -it 進入 Container 玩玩

直接使用 docker exec 進入 compose container 的 cql container 的 cqlsh。可以在這邊操作各個 container 的資料跟系統,如果有安裝 docker desktop 也可以直接開啟 container 裡面的 exec。

# 這邊的 cqlsh 跟 bash 一樣是一個 shell,但特別給 cql 語言的
user@mycomputer % docker exec -it quipu-cql-1 cqlsh
Connected to  at 172.19.0.2:9042
[cqlsh 6.2.0 | Scylla 5.4.3-0.20240211.cf42ca0c2a65 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh>