docker-composeで動かしているWebサービスで、新しいイメージを簡単にデプロイする方法を模索していたので、メモしてみます。
※あくまで簡易的なデプロイ方法なので、ダウンタイムが発生します。
例えば以下のような docker-compose.yml
を /var/www/app
に配置して運用しているとします。
docker-compose.yml
version: '2'
services:
app:
image: registry.gitlab.com/your-name/your-project:latest
container_name: app
ports:
- 8080:80
volumes:
- ./data:/app/data
depends_on:
- mongo
mongo:
image: mongo:latest
container_name: mongo
volumes:
- ./mongo:/db/data
ここで使っているregistryに最新のイメージをプッシュした後、このappサービスのコンテナを新しいイメージのものに入れ替えたい、というユースケースです。
以下のようなスクリプトを配置します。
deploy.sh
#!/bin/bash
IMAGE=registry.gitlab.com/your-name/your-project
IMAGE_TAG=latest
CONTAINER_NAME=app
CONTAINER_ID=`docker container ls -aqf "name=$CONTAINER_NAME"`
cd /var/www/app
docker image pull $IMAGE:$IMAGE_TAG
docker-compose stop $CONTAINER_NAME
docker container rm $CONTAINER_ID
docker-compose up --no-deps -d $CONTAINER_NAME
docker image rm `docker image ls -qf "dangling=true" -f "reference=$IMAGE" | tr "\n" " "`
-
docker image pull ...
:新しいイメージをプルします。このとき既存のイメージはタグが外れ、新しいイメージにタグが割り当てられます。 -
docker-compose stop ...
:appサービスのみ停止します。 -
docker container rm ...
:appサービスのコンテナを削除します。 -
docker-compose up ...
:新しいappコンテナを立ち上げます。このとき先程プルした新しいイメージが使用されます。 -
docker image rm ...
:docker image ls
で、タグが外れた(dangling)古いイメージのIDを取得し、docker image rm
でイメージを削除します。
container registryに新しいイメージをプッシュしたあと、(例えばCIからSSH経由で)このdeploy.shを叩くことで、docker-composeのappサービスが新しいイメージのものと入れ替わり、古いイメージが削除されます。
特に最後の古いイメージを削除するのを忘れてしまうと、デプロイの度にサーバーのストレージに古いイメージが溜まり、容量がどんどん圧迫されていくので要注意です。