Docker と WSL2 で開発する方法を勉強しなおす - Compose 編

昨日作った Docker の環境を、今後を見据えて Docker Compose で起動できるようにする。

環境

  • Windows10 Pro バージョン20H2
  • docker desktop 3.3.1
  • WSL2 のディストリビューションは Ubuntu 20.04

留意事項

今回の記事は 昨日の記事 の続きなので、ディレクトリ構成や Dockerfile, main.go の中身等は昨日の記事終了時のものとする。
昨日の記事終了時の中身は gitlab に置いた。 初学者の立場だとどのディレクトリでコマンドを打てばいいのかわからなくなることがあるので、むしろどこで打ってもいいようになるべく絶対パスで記述する。

本文

まずまっさらな状態にしたいので昨日作ったコンテナとイメージを消す。
docker ps -a でコンテナIDを調べて docker rm [コンテナID] でコンテナを消去。

$ docker ps -a
CONTAINER ID   IMAGE       COMMAND     CREATED        STATUS                    PORTS     NAMES
66b7305f3177   goapp:1.0   "/bin/sh"   18 hours ago   Exited (0) 16 hours ago             goapp
$ docker rm 66b7305f3177
66b7305f3177
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

docker images でイメージIDを調べて docker rmi [イメージID] でイメージを消去。

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
goapp        1.0       a163110192af   18 hours ago   301MB
$ docker rmi a163110192af
Untagged: goapp:1.0
Deleted: sha256:a163110192afbd749d3bf43cf26852a1f41a79e1a2e3d4154f0fe5de8e2c0a35
$ docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE 

次に昨日作ったディレクトリ構成はこうだが

go_docker_test
|
|-build
| |-package
|   |-Dockerfile
|
|-cmd
| |-main.go
|
|-go.mod
|-go.sum

go_docker_test ディレクトリの下に go ディレクトリを作って、その中に build ディレクトリ、cmd ディレクトリ、go.mod、go.sum を入れることにする。
そして go_docker_test ディレクトリの下に docker-compose.yml ファイルを作成する。

go_docker_test
|
|-go
| |-build
| | |-package
| |   |-Dockerfile
| |
| |-cmd
| | |-main.go
| |
| |-go.mod
| |-go.sum
|
|-docker-compose.yml

コマンドでやるとこんな感じ。

$ mkdir -p ~/go_docker_test/go
$ mv ~/go_docker_test/build ~/go_docker_test/go
$ mv ~/go_docker_test/cmd ~/go_docker_test/go
$ mv ~/go_docker_test/go.mod ~/go_docker_test/go
$ mv ~/go_docker_test/go.sum ~/go_docker_test/go
$ touch ~/go_docker_test/docker-compose.yml

作った docker-compose.yml (Compose ファイル) の中身を書いていく。

最新の Compose ファイルのフォーマットは下記にある。
https://github.com/compose-spec/compose-spec/blob/master/spec.md
たいていの Compose ファイルのサンプルには冒頭に version が書いてあるのだがもう DEPRECATED らしい。やはり一次ソースを見るに限る。

さて、昨日 Docker でイメージをビルドしてから起動するときに打ったコマンドを、今日作り直したディレクトリ構成で書き直すと下記のようになる。

$ docker build --tag goapp:1.0 ~/go_docker_test/go/build/package
$ docker run --name goapp -v ~/go_docker_test/go:/go/src/goapp -it goapp:1.0

これを Compose ファイルにするとこう。

services:
    backend:
        container_name: goapp
        image: goapp:1.0
        build: ./go/build/package
        volumes:
            - ./go:/go/src/goapp
        tty: true

各部分の意味はだいたい以下の通り。

services:
    backend:

backend という名前のサービスを作る。backend の部分は好きな名前でいい。
これは Docker Compose 独自のもの。

container_name: goapp

コンテナ名を goapp とする。
Docker 用コマンドで言うと docker run --name goapp -v ~/go_docker_test/go:/go/src/goapp -it goapp:1.0--name goapp に相当する。

image: goapp:1.0
build: ./go/build/package

~/go_docker_test/go/build/package にある Dockerfile を使って goapp:1.0 というイメージを作る。
Docker 用コマンドで言うと docker build --tag goapp:1.0 ~/go_docker_test/go/build/package に相当する。
今回は Compose ファイルが ~/go_docker_test にあるため、build のパスは ~/go_docker_test からの相対パスになっている。

volumes:
    - ./go:/go/src/goapp

ホスト側の ~/go_docker_test/go ディレクトリをコンテナ内の /go/src/goapp にマウントする。
Docker 用コマンドで言うと docker run --name goapp -v ~/go_docker_test/go:/go/src/goapp -it goapp:1.0-v ~/go_docker_test/go:/go/src/goapp に相当する。
今回は Compose ファイルが ~/go_docker_test にあるため、ホスト側のパスは ~/go_docker_test からの相対パスになっている。

tty: true

疑似 TTY(pseudo-TTY)を割り当てる。つまりコンテナ内で bash シェルを作成する。
Docker 用コマンドで言うと docker run --name goapp -v ~/go_docker_test/go:/go/src/goapp -it goapp:1.0-it に相当する。
もっと厳密に言うと -it の中の -t に相当する。(-it の中の -i は「コンテナの標準出力に接続する」の意味。)

この Compose ファイルを使ってイメージを作ってコンテナを起動する。
Compose ファイルがあるディレクトリに移動してから docker-compose up コマンドを打つ。
(※この後 Compose のコマンド打つたびに念のために cd ~/go_docker_test/ って書くけど、カレントディレクトリが ~/go_docker_test ならもちろん打たなくていい)

$ cd ~/go_docker_test/
$ docker-compose up

冒頭でイメージを削除したのでイメージの作成から行われるはず。
起動が終わって Attaching to goapp と表示されたら、新しいターミナルを開いて起動状態を確認する。

$ cd ~/go_docker_test/
$ docker-compose ps 
Name    Command   State   Ports
-------------------------------
goapp   /bin/sh   Up           

このように State が Up になっていたら起動している。このコンテナ内の bash シェルに接続する。
接続コマンドは docker-compose exec [サービス名] sh で、今回は Compose ファイルでサービス名を「backend」としたのでこう。

$ cd ~/go_docker_test/
$ docker-compose exec backend sh
/go/src/goapp # 

無事接続できたら、昨日と同じように main.go を動かしてみる。

/go/src/goapp # go run /go/src/goapp/cmd
go: downloading rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
Hello, World!
Don't communicate by sharing memory, share memory by communicating.

初回だからかなんやかんやダウンロードしたが、最終的に昨日と同じメッセージが出ればOK。

コンテナ内から exit で抜ける。
今回は exit で抜けただけではコンテナは終了しないので、終了コマンドを打って終了する。

$ cd ~/go_docker_test/
$ docker-compose down
Stopping goapp ... done
Removing goapp ... done
Removing network go_docker_test_default
$ docker-compose ps 
Name   Command   State   Ports
------------------------------

その他のコマンドは下記参照。
https://docs.docker.com/compose/reference/overview/

今日の記事終了時の中身は gitlab に置いた。
今回は終了。

参考記事