本文是《Docker必知必會系列》第七篇,原文發佈於個人博客:悟塵紀。
一、Docker Compose 概述
1、Docker Compose 是什麼
Compose
項目是 Docker
官方支持的開源項目,基於 Python 編寫,用於定義和運行多容器Docker應用程序。Compose 使用 YAML 文件來配置應用程序的服務。然後,使用一個命令,就可以從配置中創建並啓動所有服務。
!!! note “”
使用 Dockerfile
模板文件,可以讓用戶很方便的定義一個單獨的應用容器。然而,在日常工作中,經常會碰到需要多個容器相互配合來完成某項任務的情況。例如要實現一個 Web 項目,除了 Web 服務容器本身,往往還需要再加上後端的數據庫服務容器,甚至還包括負載均衡容器等。Compose
剛好可以滿足這樣的需求。
Compose 有着用於管理應用程序整個生命週期的各種命令:
- 啓動、停止和重建服務
- 查看正在運行的服務的狀態
- 實時查看運行服務的日誌輸出
- 僅執行一次命令即可運行整個服務
2、Compose 使用步驟
使用 Compose 基本上有三個步驟:
- 使用
Dockerfile
定義應用程序的環境,這樣它就可以在任何地方複製。 - 用
docker-compose. yml
定義組成應用程序的服務,使其可以在一個獨立的環境中一起運行。 - 運行
docker-Compose up
,Compose 啓動並運行您的整個應用程序。
3、典型 docker-compose 文件示例
使用 docker-compose
您主要的任務是編寫 docker-compose.yml
文件。以下是一個 WordPress
的 yaml 文件模板:
version: '3' # 定義版本,不指定默認爲版本 1
services: # 定義容器,就像 docker run
db: # 容器名稱,也是 network 中 DNS 名稱
image: mysql:5.7 # 鏡像,如果自定義鏡像可以不指定這個參數,而用 build
volumes: # 定義數據卷,類似 -v
- db_data:/var/lib/mysql
- .:/lxl80 # 掛載當前目錄到容器中的 /lxl80 目錄
restart: always # 類似 --restart。'no' 默認,不自動重啓;always 總是自動重啓; on-failure 當失敗時自動重啓;unless-stopped 除非手動停止,否者一直重啓
environment: # 定義環境變量,類似 -e
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress: # 第二個容器
labels: # 爲容器添加 Docker 元數據(metadata)信息。
cn.lixl.title: "This label will appear on all containers for the web service"
depends_on: # 定義容器之間的關係。啓動 wordpress 時會先啓動 db
- db
image: wordpress:latest
ports: # 端口,類似 -p
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes: # 可選,需要創建的數據卷,類似 docker volume create
db_data:
networks: # 可選,需要創建的網絡,類似 docker network create
二、Compose安裝及卸載
1、安裝 Compose
Docker Desktop
for Mac/Windows 自帶 docker-compose
二進制文件,安裝 Docker 之後可以直接使用。
$ docker-compose --version
docker-compose version 1.24.1, build 4667896b
在 Linux 上的也安裝十分簡單,從 官方 GitHub Release 處直接下載編譯好的二進制文件即可。
例如,在 Linux 64 位系統上直接下載對應的二進制包。
sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
2、卸載 Compose
如果基於 curl
安裝,通過以下命令卸載Docker Compose :
sudo rm /usr/local/bin/docker-compose
如果基於 pip
安裝,通過以下命令卸載Docker Compose :
pip uninstall docker-compose
三、Docker Compose 入門
關鍵術語
Compose
中有兩個重要的概念:
-
服務 (
service
):一個應用的容器,實際上可以包括若干運行相同鏡像的容器實例。 -
項目 (
project
):由一組關聯的應用容器組成的一個完整業務單元,在docker-compose.yml
文件中定義。
可見,一個項目可以由多個服務(容器)關聯而成,Compose
面向項目進行管理。
示例應用介紹
接下來,將構建一個運行在 Docker Compose 上的簡單 Python web 應用程序。 該應用程序使用了 Flask 框架,並在 Redis 維護了一個點擊計數器。
首選,需要確保已經安裝了 Docker 引擎和 Docker Compose。 不需要安裝 Python 或 Redis,因爲它們都是由 Docker 鏡像提供的。
第一步:設置
定義應用程序的依賴關係:
1、爲項目創建一個目錄:
mkdir composetest
cd composetest
2、在項目目錄中創建一個名爲 app.py 的文件,內容如下:
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
在本例中,redis 是應用程序網絡上 redis 容器的主機名。 這裏使用 Redis 的默認端口,6379。
3、在項目目錄中創建另一個叫 requirements.txt
的文件,內容如下:
flask
redis
第二步:創建一個Dockerfile
在這個步驟中,將編寫一個 Dockerfile
來構建一個 Docker 鏡像。鏡像包含 Python 應用程序所需的所有依賴項,包括 Python 本身。
在項目目錄中,創建一個名爲 Dockerfile 的文件,內容如下:
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
這告訴 Docker:
- 基於 Python 3.7 鏡像構建
- 將工作目錄設置爲
/code
- 設置
flask
命令使用的環境變量 - 安裝 gcc,以便諸如 MarkupSafe 和 SQLAlchemy 之類的 Python 包可以加速編譯
- 複製
requirements.txt
並安裝 Python 依賴項 - 將主機上的項目目錄(當前目錄)複製到鏡像中的
.
工作目錄 - 將容器的默認命令設置爲
flask run
第三步:用 Compose 文件定義服務
在項目目錄中創建一個名爲 docker-compose.yml
的文件,內容如下:
version: '3'
services:
web:
build: . # 相當於 docker build .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
此 Compose 文件定義了兩個服務:web
和 redis
。
web
服務使用從當前目錄中的 Dockerfile
構建的鏡像。然後將容器和主機綁定到公開端口 5000。 此示例服務使用 Flask web 服務器的默認端口5000。
Redis 服務使用從 dockerhub 註冊表中提取的公共 Redis 鏡像。
第四步:用 Compose 構建和運行應用
1、在項目目錄中,通過運行 docker-compose up
啓動應用程序。
$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
redis_1 | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
web_1 | * Restarting with stat
redis_1 | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379.
redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
web_1 | * Debugger is active!
redis_1 | 1:M 17 Aug 22:11:10.483 # Server initialized
redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
web_1 | * Debugger PIN: 330-787-903
redis_1 | 1:M 17 Aug 22:11:10.483 * Ready to accept connections
Compose 會拉取一個 Redis 鏡像,爲您的代碼構建一個鏡像,並啓動您定義的服務。 在這種情況下,代碼會在構建時靜態複製到鏡像中。
2、在瀏覽器中輸入 http://localhost:5000/ ,查看該應用程序的運行情況。
您應該在瀏覽器中看到一條消息,內容爲:
Hello World! I have been seen 1 times.
3、刷新頁面,數字應該會遞增。
Hello World! I have been seen 2 times.
4、切換到另一個終端窗口,鍵入 docker image ls
查看本地鏡像。此時列出的鏡像應返回 redis
和 composetest_web
。
5、要停止應用程序,可以在另一個終端中進入項目目錄運行 docker-compose stop
,或者在啓動應用程序的原始終端中按 ctrl + c
。如果要停止並清除數據,以便再次啓動後重新計數,可以執行 ``docker-compose down`。
第五步:編輯 Compose 文件添加掛載
在項目目錄中編輯 docker-compose. yml
,爲 web 服務添加一個 bind mount
:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
environment:
FLASK_ENV: development
redis:
image: "redis:alpine"
新增加 volumes
配置,將主機上的項目目錄(當前目錄)安裝到容器內部的 /code
目錄,使您可以即時修改代碼,而不必重建鏡像。新增 environment
鍵設置了 FLASK_ENV
環境變量,指示 flask run
要在開發模式下運行並在更改時重新加載代碼。此模式僅應在開發中使用。
第六步:重新構建並運行
從項目目錄中,先輸入 docker-compose stop
停止營業,然後輸入 docker-Compose up
以構建帶有更新的 Compose 文件的應用程序,並運行它。
$ docker-compose stop
Stopping composetest_web_1 ... done
Stopping composetest_redis_1 ... done
$ docker-compose up
Recreating composetest_web_1 ... done
Starting composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1 | 1:C 17 Apr 2020 02:25:49.466 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
......
web_1 | * Serving Flask app "app.py" (lazy loading)
web_1 | * Environment: development
web_1 | * Debug mode: on
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 143-909-154
再次檢查瀏覽器中的 Hello World 提示消息,並刷新以查看計數增量。
如果出現運行時錯誤指示找不到應用程序文件,拒絕卷安裝或服務無法啓動,請嘗試啓用文件或驅動器共享。有關更多信息,請參閱 Docker for Mac 上的 文件共享 章節。
第七步:更新應用程序
因爲現在應用程序代碼是使用卷安裝到容器中的,所以可以對代碼進行更改並立即生效,而無需重建鏡像。
-
更改
app.py
中的提示語並保存。例如,將Hello World!
更改爲Hello from Docker!
:return 'Hello from Docker! I have been seen {} times.\n'.format(count)
-
在瀏覽器中刷新應用。會發現提示語已更新,並且計數器仍在增加。
第八步:嘗試其它命令
如果要讓服務在後臺運行,可以將 -d
參數(用於“分離”模式)傳遞給 docker-compose up
,並用 docker-compose ps
查看當前正在運行的內容:
$ docker-compose up -d
Starting composetest_web_1 ... done
Starting composetest_redis_1 ... done
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------
composetest_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
composetest_web_1 flask run Up 0.0.0.0:5000->5000/tcp
docker-compose run
命令允許爲服務運行一次性命令。 例如,查看 web
服務可用的環境變量:
$ docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=4b3f1e39dc5d
......
FLASK_APP=app.py
FLASK_RUN_HOST=0.0.0.0
HOME=/root
請參閱 docker-compose --help
以查看其他可用命令。您還可以爲 bash 和 zsh shell 安裝 命令補全 功能,這將自動提示可用的命令。