# Docker 實戰 3 - Docker-compose ## 前言 前兩篇和大家介紹了什麼是Docker以及 Dockerfile的寫法 - [Docker 實戰 1 - 五分鐘了解 Docker](/lo88XIBlTiGJeiUDs8JmFw) - [Docker 實戰 2 - 相關指令與Dockerfile](https://hackmd.io/@emmmmmma/ikFuYeHLRdeSM6p88_IhKA) 前面提到透過Dockerfile建立image並且用docker run的指令建立容器執行image,但如果同時有好幾的image要執行呢?例如寫後端的時候,除了建立後端的image之外,通常還會有資料庫的環境,換言之沒有compose的情況下就要執行兩次docker run,後續也會不好管理。這時候可以管理多個 Container 的工具 docker-compose就登場啦! ## Docker Compose - 簡單來說Compose就是一個管理container的工具 - 檔名是.yml docker-compose.yml,只要把要執行的image寫進檔案裡面 ## 常用指令 實作的部份主要就是要把 Docker-Compose 安裝起來,然後撰寫一個 docker-compose.yml,並且使用 docker-compose up,指令把所有的 Docker Container 啟動起來,步驟如下: - 建立和刪除 container docker-compose up docker-compose down > 在後面加上 -d ,就會在背景執行 - 起重和停止 container docker-compose start docker-compose stop > docker-compose up與docker-compose start最大的差別在於,前者可以從0到有建立image和container但後者只能啟動已經建立的container而已 - 查看運行中的conatiner docker-compose ps > 和docker指令相似,用ps就可以列出所有資訊 ## docker-compose.yml ### 基本語法 - version:使用哪個版本的語法,現在通常用3以上的版本 - services:設定容器的單位通稱為service,一個 service 設定可以用來啟動多個 container - network : 沒有設定的話就代表services底下的container會被加入到一個預設的myapp_default網路中, ### 實作 Docker container 以下教大家幾個常用的docker-compose.yml寫法 #### 已經建立好image 1. 如果先前已經在前後端的資料夾中使用docker build建立個別的image,就可以建立一個docker-compose.yml檔案,並在裡面直接宣告image名稱 ```dockerfile= version: "3.9" #版本宣告 services: frontend: # 宣告 service的名稱 image: frontend-image # 宣告要run起來的image名稱 ports: - '3000:3000' # 設定port restart: always # 如果server掛掉了會自動重啟 server: image: backend-image # 宣告要run起來的image名稱 ports: - '3311:3311' restart: always ``` #### 執行的時候一起建立image build會根據你設定的路徑去找該路徑底下的Dockerfile檔案去建立image ```dockerfile= version: "3.9" #版本宣告 services: frontend: # 宣告 service的名稱 build: ./frontend # 宣告建立image的路徑 ports: - '3000:3000' # 設定port restart: always # 如果server掛掉了會自動重啟 server: build: ./backend # 宣告要run起來的image名稱 ports: - '3311:3311' restart: always ``` :::warning :writing_hand: 宣告image和build的差別在於,如果是放在虛擬機上部署,前者只需要用docker load的方式把image抓下來就可以使用了,後者變成要把整份程式碼上傳才行,相對來說會不安全一點點。 ::: #### 加入資料庫 下方範例加入network的範例,當我們夠過docker部署,且外界要連上網址時,docker預設的網路模式bridge會出現一些問題(本篇不會詳細介紹),所以大家只先記得,透過設定network可以讓容器內外部的溝通更加方便! ```dockerfile= version: "3.9" networks: shared: services: frontend: image: analytic-frontend ports: - "3000:3000" networks: - shared restart: always server: image: analytic-server ports: - '5006:5006' depends_on: - db environment: DB_HOST: db DB_USER: docker DB_PASSWORD: 1234 DATABASE_URL: "postgresql://docker:1234@db:5432/docker" networks: - shared restart: always db: image: 'postgres' ports: - '5432:5432' environment: POSTGRES_DB: docker POSTGRES_PASSWORD: 1234 POSTGRES_USER: docker networks: - shared volumes: - ./postgres:/var/lib/postgresql/data nginx: image: 'nginx' ports: - "8080:80" volumes: - ./nginx.conf:/etc/conf.d ``` ## 總結 恭喜大家看完Docker系列的教學啦,至於後面的兩個大坑暫時還不會教,因為我自己也還沒仔細研究XD 總之,只要能先把docker還有docker-compose學好,理論上可以解決80%的問題啦! ![](https://hackmd.io/_uploads/SJDq_D_kT.png) ## 參考資料 - [Compose file version 3 reference](https://docs.docker.com/compose/compose-file/compose-file-v3/) - [Networking in Compose](https://docs.docker.com/compose/networking/) - [三周目 - Docker network](https://ithelp.ithome.com.tw/articles/10206725)