docker-compose

公式チュートリアル。python+flaskフロントエンド、redisバックエンドのシンプル構成。

Step 1: Setup

フォルダーdocker_compose作成

1
2
mkdir docker_compose
cd docker_compose

フォルダー内にapp.py作成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)

インストールするpythonモジュールをrequirements.txt

1
2
flask
redis

Step 2: Create a Dockerfile

Dockerの設定ファイルをDockerfileで作成。

1
2
3
4
5
6
7
8
9
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"]

Step 3: Define services in a Compose file

2つのdockerを起動するdocker-compose.ymlを作成。webredisの2つのDocker Containerを起動する。webはSTEP2のDockerfileを使用してDocker Containerを起動し、port5000で待ち受け、redisはredis:aplineイメージをpullしてカスタマイズなしで使用する。

1
2
3
4
5
6
7
8
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"

Step 4: Build and run your app with Compose

docker-compose upで起動する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
PS > docker-compose up
Building web
Step 1/9 : FROM python:3.7-alpine
3.7-alpine: Pulling from library/python
89d9c30c1d48: Pulling fs layer
89d9c30c1d48: Downloading [> ] 29.23kB/2.7
87MB415eb85a: Downloading [> ] 293.6kB/28.
910c49c00810: Downloading [> ] 3.222kB/301
89d9c30c1d48: Downloading [====> ] 277.6kB/2.7
87MB415eb85a: Downloading [==> ] 1.195MB/28.
910c49c00810: Downloading [=====================> ] 127kB/301
910c49c00810: Downloading [==================================================>] 301.7kB/301
89d9c30c1d48: Downloading [=============> ] 752.3kB/2.7
89d9c30c1d48: Extracting [===========================================> ] 2.425MB/2.78
89d9c30c1d48: Extracting [==================================================>] 2.787MB/2.78
910c49c00810: Extracting [==================================================>] 301.7kB/301.
7efe415eb85a: Pull complete
7d8d53519b81: Extracting [==================================================>] 231B/231B
7d8d53519b81: Extracting [==================================================>] 231B/231B
7d8d53519b81: Pull complete
519124ac136c: Pull complete
Digest: sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf
Status: Downloaded newer image for python:3.7-alpine
---> 8922d588eec6
Step 2/9 : WORKDIR /code
---> Running in 9150eb4151ea
Removing intermediate container 9150eb4151ea
---> ecccd64cc137
Step 3/9 : ENV FLASK_APP app.py
---> Running in e3b87df8a938
Removing intermediate container e3b87df8a938
---> 7f7e2af72efa
Step 4/9 : ENV FLASK_RUN_HOST 0.0.0.0
---> Running in 0e4a9910abce
Removing intermediate container 0e4a9910abce
---> c220db73c816
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/12) Installing binutils (2.32-r0)
(2/12) Installing gmp (6.1.2-r1)
(3/12) Installing isl (0.18-r0)
(4/12) Installing libgomp (8.3.0-r0)
(5/12) Installing libatomic (8.3.0-r0)
(6/12) Installing libgcc (8.3.0-r0)
(7/12) Installing mpfr3 (3.1.5-r1)
(8/12) Installing mpc1 (1.1.0-r0)
(9/12) Installing libstdc++ (8.3.0-r0)
(10/12) Installing gcc (8.3.0-r0)
(11/12) Installing linux-headers (4.19.36-r0)
(12/12) Installing musl-dev (1.1.22-r3)
Executing busybox-1.30.1-r2.trigger
OK: 121 MiB in 47 packages
Removing intermediate container 3ac74409efbf
---> 64589c0f27d3
Step 6/9 : COPY requirements.txt requirements.txt
---> 73cf869e71e5
Step 7/9 : RUN pip install -r requirements.txt
---> Running in 574d2aaab6a8
Collecting flask
Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
Collecting redis
Downloading https://files.pythonhosted.org/packages/32/ae/28613a62eea0d53d3db3147f8715f90da07667e99baeedf1010eb400f8c0/redis-3.3.11-py2.py3-none-any.whl (66kB)
Collecting Werkzeug>=0.15
Downloading https://files.pythonhosted.org/packages/ce/42/3aeda98f96e85fd26180534d36570e4d18108d62ae36f87694b476b83d6f/Werkzeug-0.16.0-py2.py3-none-any.whl (327kB)
Collecting itsdangerous>=0.24
Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting Jinja2>=2.10.1
Downloading https://files.pythonhosted.org/packages/65/e0/eb35e762802015cab1ccee04e8a277b03f1d8e53da3ec3106882ec42558b/Jinja2-2.10.3-py2.py3-none-any.whl (125kB)
Collecting click>=5.1
Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
Collecting MarkupSafe>=0.23
Downloading https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz
Building wheels for collected packages: MarkupSafe
Building wheel for MarkupSafe (setup.py): started
Building wheel for MarkupSafe (setup.py): finished with status 'done'
Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-cp37-cp37m-linux_x86_64.whl size=32314 sha256=64efa0058f83c4e0d8a39fa0d6201593fa7a11bf6596e04606b0e67da2a2d3c5
Stored in directory: /root/.cache/pip/wheels/f2/aa/04/0edf07a1b8a5f5f1aed7580fffb69ce8972edc16a505916a77
Successfully built MarkupSafe
Installing collected packages: Werkzeug, itsdangerous, MarkupSafe, Jinja2, click, flask, redis
Successfully installed Jinja2-2.10.3 MarkupSafe-1.1.1 Werkzeug-0.16.0 click-7.0 flask-1.1.1
itsdangerous-1.1.0 redis-3.3.11
Removing intermediate container 574d2aaab6a8
---> 1bf5991056e4
Step 8/9 : COPY . .
---> a781b9ba80ff
Step 9/9 : CMD ["flask", "run"]
---> Running in b36fae1519a9
Removing intermediate container b36fae1519a9
---> 5b84b8389657
Successfully built 5b84b8389657
Successfully tagged docker_compose_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this i
b2eb22a0b7db: Extracting [==================================================>] 1.255kB/1.25
b2eb22a0b7db: Extracting [==================================================>] 1.255kB/1.25
5kBine: Pulling from library/redis
c5ccbdf10203: Pull complete
592c37d15428: Pull complete
b70a614994bf: Downloading [==================================================>] 99B/99B
b70a614994bf: Extracting [==================================================>] 99B/99B
b70a614994bf: Pull complete
60027bdc030c: Pull complete
Digest: sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
Status: Downloaded newer image for redis:alpine
Creating docker_compose_redis_1 ... done
Creating docker_compose_web_1 ... done
Attaching to docker_compose_redis_1, docker_compose_web_1
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 14 Dec 2019 16:28:27.388 * Running mode=standalone, port=6379.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # WARNING: The TCP backlog setting of 511 cannot be
enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # Server initialized
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # 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.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 * Ready to accept connections
web_1 | * Serving Flask app "app.py"
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

起動後、http://127.0.0.1:5000にアクセス。

チュートリアル画面1 width=640

redis(Key-Valueストア)にカウンターが記録されていくため、アクセス毎にカウントアップしていくデモになっている。

Step 5: Edit the Compose file to add a bind mount

docker-compose.ymlを編集して、volumesenvironmentを追加。
volumesでホストのカレントフォルダー(app.pyのあるフォルダー)をcodeというディレクトリ名(Dockerfileでapp.pyを配置するフォルダー)で参照する。
environmentは環境変数FLASK_ENVを設定し、flask runflaskdevelopment modeで動作する。

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
environment:
FLASK_ENV: development
redis:
image: "redis:alpine"

Step 6: Re-build and run the app with Compose

docker-compose upでContainerを起動し、app.pyのメッセージを編集する。development modeで動作しているので、デバッグログによってapp.pyの変更が検出されていることを確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PS > docker-compose up
Creating network "docker_compose_default" with the default driver

…略…

Attaching to docker_compose_web_1, docker_compose_redis_1
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 14 Dec 2019 18:22:40.379 * Running mode=standalone, port=6379.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # WARNING: The TCP backlog setting of 511 cannot be
enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # Server initialized
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # 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.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 * Ready to accept connections
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: 318-738-267
web_1 | 172.20.0.1 - - [14/Dec/2019 18:23:32] "GET / HTTP/1.1" 200 -
web_1 | * Detected change in '/code/app.py', reloading
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 318-738-267
web_1 | 172.20.0.1 - - [14/Dec/2019 18:24:49] "GET / HTTP/1.1" 200 -

変更後は動的にメッセージが変更されていることがわかる。

チュートリアル画面2 width=640

Step 8: Experiment with some other commands

docker-composeで起動しているContainerの状態はdocker-compose psで表示できる。

1
2
3
4
5
6
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp

docker-composeをバックグラウンドで動作させるのはdocker-compose up -d、停止はdocker-compose stop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0
PS > docker-compose up -d
Starting docker_compose_redis_1 ... done
Starting docker_compose_web_1 ... done
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp
PS > docker-compose stop
Stopping docker_compose_web_1 ... done
Stopping docker_compose_redis_1 ... done
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0

コンテナイメージを指定して、コマンド実行を行うにはdocker-compose run [コマンド名]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PS > docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0cbfdb243a0c
TERM=xterm
FLASK_ENV=development
LANG=C.UTF-8
GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
PYTHON_VERSION=3.7.5
PYTHON_PIP_VERSION=19.3.1
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/ffe826207a010164265d9cc807978e3604d18ca0/get-pip.py
PYTHON_GET_PIP_SHA256=b86f36cc4345ae87bfd4f10ef6b2dbfa7a872fbff70608a1e43944d283fd0eee
FLASK_APP=app.py
FLASK_RUN_HOST=0.0.0.0
HOME=/root
PS > docker-compose run web pip list
Package Version
------------ -------
Click 7.0
Flask 1.1.1
itsdangerous 1.1.0
Jinja2 2.10.3
MarkupSafe 1.1.1
pip 19.3.1
redis 3.3.11
setuptools 41.6.0
Werkzeug 0.16.0
wheel 0.33.6

redisContainerのボリュームを削除する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS > docker volume ls
DRIVER VOLUME NAME
local 7c43ed5a237f7bf1d723c67f649a9beebc963a1cc382296144520266401828ed
local 15ed5c9b93d2d610a40b25269455a56aacf77e7211481820738a0cb696b31119
local 66c0d8f05167232b7ab4760d21450439b95cc1f01fc26a3309e821574f445fd0
local de7a255c91c675252901156114743ef68aa7ef2f7daf82818e3899df7499ee17
PS > docker-compose down --volumes
Removing docker_compose_web_run_276ed55e0300 ... done
Removing docker_compose_web_run_906711b02696 ... done
Removing docker_compose_web_run_39db7500d084 ... done
Removing docker_compose_web_run_ec0d0bdb628d ... done
Removing docker_compose_web_run_54937947aa1f ... done
Removing docker_compose_web_1 ... done
Removing docker_compose_redis_1 ... done
Removing network docker_compose_default
PS > docker volume ls
DRIVER VOLUME NAME
local 15ed5c9b93d2d610a40b25269455a56aacf77e7211481820738a0cb696b31119
local 66c0d8f05167232b7ab4760d21450439b95cc1f01fc26a3309e821574f445fd0
local de7a255c91c675252901156114743ef68aa7ef2f7daf82818e3899df7499ee17

dockerとdocker-compose基本操作

docker-composeで起動したContainerの停止

docker-compose upで起動すると、docker-compose.ymlで定義したContainerがすべて起動された状態になっている。docker-composeで起動したdockerを停止させると(今回はCtrl+Cで停止)すべてのContainerが停止する。

1
2
3
4
5
6
7
8
9
10
11
12
web_1    |  * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Gracefully stopping... (press Ctrl+C again to force)
Stopping docker_compose_web_1 ... done
Stopping docker_compose_redis_1 ... done
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 29 minutes ago Exited (137) 3 minutes ago docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 29 minutes ago Exited (0) 3 minutes ago docker_compose_redis_1

Containerとイメージの一覧

Dockerはdocker images -aでイメージ一覧を、docker ps -aで停止中のものを含めたContainerの状態を確認できる。

docker-composeDocker HUBから取得したイメージをそのまま使用しているredisredisイメージのみがある。Dockerfileでカスタマイズしたイメージはdocker_compose_webイメージと元にしたpythonイメージがある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 29 seconds ago 213MB
<none> <none> a781b9ba80ff 30 seconds ago 213MB
<none> <none> 1bf5991056e4 30 seconds ago 213MB
<none> <none> 73cf869e71e5 34 seconds ago 202MB
<none> <none> 64589c0f27d3 34 seconds ago 202MB
<none> <none> ecccd64cc137 41 seconds ago 98.4MB
<none> <none> 7f7e2af72efa 41 seconds ago 98.4MB
<none> <none> c220db73c816 41 seconds ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 30 seconds ago Up 28 seconds 0.0.0.0:5000->5000/tcp docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 30 seconds ago Up 28 seconds 6379/tcp docker_compose_redis_1

docker-composeで制御しているContainerはdocker-compose psで、イメージはdocker-compose imagesで確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0
PS > docker-compose images
指定されたパスが見つかりません。
Container Repository Tag Image Id Size
-----------------------------------------------------------------------------
docker_compose_redis_1 redis alpine a49ff3e0d85f 27.9 MB
docker_compose_web_1 docker_compose_web latest a460579f2e03 203 MB

起動中のContainerに対するコマンド実行

起動中のContainerのシェルへアクセスするにはdocker exec -it [コンテナ名] [コマンド名]を使う。alpineはbashがないので/bin/ashを指定する。

1
2
3
4
5
6
7
8
9
10
11
12
13
PS > docker-compose up
Creating network "docker_compose_default" with the default driver

…略…

PS > docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac1ba1951edb redis:alpine "docker-entrypoint.s…" About a minute ago Up 15 seconds 6379/tcp docker_compose_redis_1
6681c0eff91c docker_compose_web "flask run" About a minute ago Up 15 seconds 0.0.0.0:5000->5000/tcp docker_compose_web_1
PS > docker exec -it ac1ba1951edb /bin/ash
/data #
/data # ls
dump.rdb

docker-composeを使う場合はdocker-compose exec [サービス名] [コマンド名]で操作できる

1
2
3
4
5
6
7
8
9
PS > docker-compose exec web ash
/code # ls
Dockerfile app.py requirements.txt
__pycache__ docker-compose.yml
/code # exit
PS > docker-compose exec redis ash
/data # ls
dump.rdb
/data # exit

Containerを起動して一度だけコマンド実行を行う

イメージからContainerを新しく起動する場合はdocker run [イメージ名] [コマンド名]

1
2
3
4
5
6
7
8
9
10
11
PS > docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest a460579f2e03 About an hour ago 213MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker run docker_compose_web /bin/ash
PS > docker run -it docker_compose_web /bin/ash
/code # ls
Dockerfile app.py requirements.txt
__pycache__ docker-compose.yml
/code # exit

docker-composeを使う場合はdocker-compose run [サービス名] [コマンド名]で操作できる。

ただし、runで実行した場合、EXPOSEで待ち受けたポートへアクセスできないので注意。

1
2
PS > docker-compose run redis ash
/data # exit

イメージのビルドで失敗し後のゴミ(キャッシュ)を使わないでビルドする

ビルドで失敗したときはキャッシュを使用しないでビルドする必要がある。docker-compose build --no-cacheでキャッシュを使用しないでビルドできる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS > docker-compose up
Creating network "docker_compose_default" with the default driver
Creating docker_compose_web_1 ... error

ERROR: for docker_compose_web_1 Cannot start service web: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"flask\": executable file not found in $PATH": unknown

ERROR: for web Cannot start service web: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"flask\": executable file not found in $PATH": unknown
ERROR: Encountered errors while bringing up the project.
PS > docker-compose build --no-cache
Building web
Step 1/9 : FROM python:3.7-alpine
---> 8922d588eec6

…略…

---> 84e5766c1f33
Step 9/9 : CMD ["ash", "run"]
---> Running in 66b174736c70
Removing intermediate container 66b174736c70
---> 7f671efb3d2b
Successfully built 7f671efb3d2b

<none>:<none>イメージとシステムのクリーンナップ

初見でわかりにくいのが、REPOSITORY:TAG<none>:<none>イメージの存在。

結論からいえば、The Good <none>:<none>The Bad <none>:<none>がある(参考:What are Docker <none>:<none> images?)。

docker images -aでのみ見えるものがThe Good <none>:<none>でDockerイメージのレイヤー構造に起因したものなのでレイヤー構造を理解しないといけない。The Bad <none>:<none>は他から参照されていないのに存在するゴミでdanglingイメージ(宙ぶらりん?)と呼ばれている。

チュートリアルのビルドログを見ると、イメージの追加削除をくりかえしていることがわかる
最初にpythonイメージがpullされ作成される(これは残っている)

1
2
3
4
5
6
Step 1/9 : FROM python:3.7-alpine

…略…

Status: Downloaded newer image for python:3.7-alpine
---> 8922d588eec6

操作する毎に中間イメージ作成削除を繰り返していく……(これらは残っていない)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Step 2/9 : WORKDIR /code
---> Running in 9150eb4151ea
Removing intermediate container 9150eb4151ea
---> ecccd64cc137
Step 3/9 : ENV FLASK_APP app.py
---> Running in e3b87df8a938
Removing intermediate container e3b87df8a938
---> 7f7e2af72efa
Step 4/9 : ENV FLASK_RUN_HOST 0.0.0.0
---> Running in 0e4a9910abce
Removing intermediate container 0e4a9910abce
---> c220db73c816
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf

…略…

Removing intermediate container 3ac74409efbf
---> 64589c0f27d3
Step 6/9 : COPY requirements.txt requirements.txt
---> 73cf869e71e5
Step 7/9 : RUN pip install -r requirements.txt
---> Running in 574d2aaab6a8

…略…

Removing intermediate container 574d2aaab6a8
---> 1bf5991056e4
Step 8/9 : COPY . .
---> a781b9ba80ff

最後にdocker_compose_webイメージが生成されて終わる。

1
2
3
4
5
Step 9/9 : CMD ["flask", "run"]
---> Running in b36fae1519a9
Removing intermediate container b36fae1519a9
---> 5b84b8389657
Successfully built 5b84b8389657

danglingイメージdocker image pruneでクリーンナップできるが、これらThe Good <none>:<none>は消えない。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS > docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 29 minutes ago 213MB
<none> <none> a781b9ba80ff 29 minutes ago 213MB
<none> <none> 1bf5991056e4 29 minutes ago 213MB
<none> <none> 73cf869e71e5 29 minutes ago 202MB
<none> <none> 64589c0f27d3 29 minutes ago 202MB
<none> <none> 7f7e2af72efa 29 minutes ago 98.4MB
<none> <none> c220db73c816 29 minutes ago 98.4MB
<none> <none> ecccd64cc137 29 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 29 minutes ago Exited (137) 3 minutes ago docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 29 minutes ago Exited (0) 3 minutes ago docker_compose_redis_1

次に停止中のContainerを削除する。削除はdocker container pruneでまとめて削除できる。
そのあとにdocker image pruneでイメージのクリーンナップしてもThe Good <none>:<none>が消えることはない。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
PS > docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
73c9ed48c34aaa7cebf06ae40ceca5c8389675e67798868f7df13e7a51e79840

Total reclaimed space: 461kB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 45 minutes ago 213MB
<none> <none> 1bf5991056e4 45 minutes ago 213MB
<none> <none> a781b9ba80ff 45 minutes ago 213MB
<none> <none> 64589c0f27d3 45 minutes ago 202MB
<none> <none> 73cf869e71e5 45 minutes ago 202MB
<none> <none> c220db73c816 45 minutes ago 98.4MB
<none> <none> ecccd64cc137 45 minutes ago 98.4MB
<none> <none> 7f7e2af72efa 45 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 46 minutes ago 213MB
<none> <none> a781b9ba80ff 46 minutes ago 213MB
<none> <none> 1bf5991056e4 46 minutes ago 213MB
<none> <none> 73cf869e71e5 46 minutes ago 202MB
<none> <none> 64589c0f27d3 46 minutes ago 202MB
<none> <none> 7f7e2af72efa 46 minutes ago 98.4MB
<none> <none> c220db73c816 46 minutes ago 98.4MB
<none> <none> ecccd64cc137 46 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB

Containerから参照されていないイメージはdocker image prune -aでまとめて削除できる。
今度はdocker image prune -aで削除してみる。The Good <none>:<none>も消えるが、参照されていないすべてのものが消える。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
PS > docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: redis:alpine
untagged: redis@sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
deleted: sha256:a49ff3e0d85f0b60ddf225db3c134ed1735a3385d9cc617457b21875673da2f0
deleted: sha256:f0bc82535d2e3250dad8edf9a8e5ad9f24ee27744393a2c781d36e785498c844
deleted: sha256:1fbf3f39fa220d3b6981fa59b146ee7c5581d39ffb33d1b45685e55bb5cc4c0b
deleted: sha256:48a9a7273f3245a05749ab53f3e5de1721802409fb422419f72c8ca1661869f6
deleted: sha256:e8d9b8d29a84e15b68e4e85f51fe3d50692c5e4cbefa9e7e1005c336734acd55
deleted: sha256:56ee7a6ab270cd80ff8ff38e4a966d311ea53174a60721a62f061efd42c426b3
untagged: docker_compose_web:latest
deleted: sha256:5b84b83896579e86516cdae855c5ad88567bef4086c0866575db89944a23783a
deleted: sha256:560e8806fc52a1cda02805458af3243aa14ec0dfb2068fd401a0e2b14afa8565
deleted: sha256:1bf5991056e4978695a8cf395e398f8655c02d77225f7df3f9b226d176f2291d
deleted: sha256:c9648df40ed18e44c7af492656899b23242a56fd3de3d1e6426f74a5d9c095e3
deleted: sha256:73cf869e71e50d2ef9dda69e8bc23a5275c70194f40534eb831de30fda59eb0e
deleted: sha256:cac7e434b98cf26674aa4e2cb6a17d2be78c22cba899689b5b630774c744d2b8
deleted: sha256:64589c0f27d34132e7eda1aa2012acbf7c8f1d461e382069e452481046fff4e4
deleted: sha256:8df494eabb2663ef5ca5cef25ba7a19941b9ea950b38eb74e2e69ad4b55ef1c1
deleted: sha256:c220db73c81631cb3b2b2ab13cd6d5bf36b26dc4069eba1ffda06ca297c83590
deleted: sha256:7f7e2af72efaa4004d49a92afdec5973ba78036be1528c31eb60fd1ad73beda5
deleted: sha256:ecccd64cc1377d9f940b614c4b28a95eec9c071af90b9a1f921e4e0741ff12dc
deleted: sha256:b2ed5645e18c07e3cf8998599b78707129f5acaf1d599ab25d5d0a0b236a43a3
untagged: python:3.7-alpine
untagged: python@sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf
deleted: sha256:8922d588eec695e9ec9e7f7cded1eea0760cb6fe7a8e46092ec12ede474f74e1
deleted: sha256:1aa13cc7d1ee07997279eab07ab1647ee0b3fd360c13486f67034b202100dc29
deleted: sha256:f298bab69f60c995202757bcc8691c1905d4d3a713ba22e96aa7369d53172a7d
deleted: sha256:7cb29a35ad37814ef19699d89f2e461360c010b9acc33a7467490d038f4a007d
deleted: sha256:44a0460612107556df9d2a0a172fae2218986bf496f7cecfdc1354aacca393bc
deleted: sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0

Total reclaimed space: 236.8MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE

Containerは停止状態とするが、削除せず存在している状態で、docker image prune -aを試す。Containerからの参照があるので、The Good <none>:<none>を含めすべて残っている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
497b14b9d4a8 redis:alpine "docker-entrypoint.s…" 33 seconds ago Exited (0) 21 seconds ago docker_compose_redis_1
cb13ceef58a6 docker_compose_web "flask run" 33 seconds ago Exited (137) 11 seconds ago docker_compose_web_1
PS > docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: python:3.7-alpine
untagged: python@sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf

Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 7c27de23c598 About a minute ago 213MB
docker_compose_web latest be361c03fae8 About a minute ago 213MB
<none> <none> 729dfa99b333 About a minute ago 213MB
<none> <none> 55ae4fb24b6c About a minute ago 202MB
<none> <none> 4b9d4224f8df About a minute ago 202MB
<none> <none> 269867bb5613 About a minute ago 98.4MB
<none> <none> 52f58b988872 About a minute ago 98.4MB
<none> <none> 05447f1997bf About a minute ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
<none> <none> 8922d588eec6 4 weeks ago 98.4MB

まっさらにする

Containerは定義ファイルから同じ環境を再構築できるのが利点なので、気軽にまっさらにできる。起動中のContainerも含めてすべてクリーンナップするにはdocker system prune -aを実行する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest be361c03fae8 44 minutes ago 213MB
<none> <none> 7c27de23c598 44 minutes ago 213MB
<none> <none> 729dfa99b333 44 minutes ago 213MB
<none> <none> 55ae4fb24b6c 44 minutes ago 202MB
<none> <none> 4b9d4224f8df 44 minutes ago 202MB
<none> <none> 269867bb5613 44 minutes ago 98.4MB
<none> <none> 05447f1997bf 44 minutes ago 98.4MB
<none> <none> 52f58b988872 44 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
<none> <none> 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
497b14b9d4a8 redis:alpine "docker-entrypoint.s…" 44 minutes ago Exited (0) 43 minutes ago docker_compose_redis_1
cb13ceef58a6 docker_compose_web "flask run" 44 minutes ago Exited (137) 43 minutes ago docker_compose_web_1
PS > docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache

Are you sure you want to continue? [y/N] y
Deleted Containers:
497b14b9d4a834770e6315c849e7d314903134f4063d687f1f82d65eb7765cb6
cb13ceef58a603a3a9511890a092df41e1550a96d95aafa26d8ed3abb2a8dd48

Deleted Networks:
docker_selenium_default
docker_compose_default

Deleted Images:
untagged: docker_compose_web:latest
deleted: sha256:be361c03fae88264f599f6a23996a2de6e2c8a3432d021d0625e018a38d3b0aa
deleted: sha256:7c27de23c5988016c9146a59883033c9dde4e3ebc8eba97138f610ed12421c0c
deleted: sha256:dd362dadecc9aa168ea1fa3995a2fbde78aa73436ea75214a4ccdb18f2bf680c
deleted: sha256:729dfa99b33392c73bae77bc2285c6562fb10ca2726e9040d217c308bff91da8
deleted: sha256:fb5f5130fd197490bd5880b5ee0e4d18a1183243b89c6d0af1924f280bac2eff
deleted: sha256:55ae4fb24b6c06800a5ca9db8967ee6b663a99c827dd5a1310025f7351482ce7
deleted: sha256:7dfcd6f95d80c8ba6d2cdcbdb1b38021daf05004f8dd4666f3bdac3339a8b050
deleted: sha256:461ac6c9722d91ef0f942676fa1508a28e41ef69c59b11c4fc0875860031f912
deleted: sha256:05447f1997bf9712fff19a914e733eda7828acd9495948c66a28bd14436f21c4
deleted: sha256:52f58b988872ed051ff895537b9aed526cf59e9951003994c6ba1037113f22fc
deleted: sha256:dc18d15a91c75af007af66a91e21af80d57239ecb94864c46c6cec3d2f3a80f6
deleted: sha256:8922d588eec695e9ec9e7f7cded1eea0760cb6fe7a8e46092ec12ede474f74e1
deleted: sha256:1aa13cc7d1ee07997279eab07ab1647ee0b3fd360c13486f67034b202100dc29
deleted: sha256:f298bab69f60c995202757bcc8691c1905d4d3a713ba22e96aa7369d53172a7d
deleted: sha256:7cb29a35ad37814ef19699d89f2e461360c010b9acc33a7467490d038f4a007d
deleted: sha256:44a0460612107556df9d2a0a172fae2218986bf496f7cecfdc1354aacca393bc
untagged: redis:alpine
untagged: redis@sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
deleted: sha256:a49ff3e0d85f0b60ddf225db3c134ed1735a3385d9cc617457b21875673da2f0
deleted: sha256:f0bc82535d2e3250dad8edf9a8e5ad9f24ee27744393a2c781d36e785498c844
deleted: sha256:1fbf3f39fa220d3b6981fa59b146ee7c5581d39ffb33d1b45685e55bb5cc4c0b
deleted: sha256:48a9a7273f3245a05749ab53f3e5de1721802409fb422419f72c8ca1661869f6
deleted: sha256:e8d9b8d29a84e15b68e4e85f51fe3d50692c5e4cbefa9e7e1005c336734acd55
deleted: sha256:56ee7a6ab270cd80ff8ff38e4a966d311ea53174a60721a62f061efd42c426b3
deleted: sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0

Total reclaimed space: 237.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE