`docker-compose up`って何？

## はじめに

Dockerに慣れ親しんできて、「そろそろ復数のDockerイメージ・コンテナを使って開発するかー」というレベルの方は多いかと思います。

私もその一人なのですが、いざリファレンスを読みながら使ってみても上手く扱えずに開発が滞ってしまうことがありました。

今回は、そのなかでも一番基本的で、かつわからないと結構ドツボにハマる`docker-compose up`についての解説を書いてみました。

自身も初学者ですので、もし誤りがあればご指摘いただけると助かります。

## 前提

今回はコマンドの説明のために、１つのコンテナを起動させるシンプルなプロジェクトを想定してみます。

### ディレクトリ構成

```bash
.
├── Dockerfile
├── docker-compose.yml
├── file.txt
└── file2.txt
```

### Dockerfile、docker-compose.ymlの内容

```Dockerfile
FROM ubuntu:18.04

WORKDIR work

ADD ./file.txt /work/file.txt

CMD ["ls"]
```

```docker-compose.yml
version: '3.7'
services:
  test:
    build: .
    image: my-alpine-image
    container_name: my-apline
```

## とりあえず"up"してみよう

上記の構成で`docker-compose up`をしてみると何が起こるか確認しましょう。

```bash
$ docker-compose up
Building test
// Stepは省略

Successfully built ff8e7d96a995
Successfully tagged my-alpine-image:latest
WARNING: Image for service test was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating my-apline ... done
Attaching to my-apline
my-apline | file.txt
my-apline exited with code 0
```

ここで重要なのは次の２点です。

* `my-alpine-image`というイメージを作成している
* `my-alpine`というコンテナを作成している

つまりは`docker run`と同じです。実際にイメージやコンテナを確認してみます。

```bash
$ docker ps -a     
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
6d14fde119f0        my-alpine-image     "/bin/bash"              10 minutes ago      Exited (0) 10 minutes ago                       my-apline
```

```bash
$ REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
my-alpine-image            latest              ff8e7d96a995        10 minutes ago        64.2MB
```

またコンソールには`my-apline | file.txt`と出力されているように、file.txtが含まれていることもわかります。

復数コンテナであってもこの動きは変わりません。そのため、**ここで「なるほど、DockerComposeは理解した」となり、このあとの勘違いにつながります。**

## Dockerfileを修正してもう一度upしてみる

つぎにDockerfileを修正して、test2.txtもコンテナに含めるようにしましょう。

```Dockerfile
FROM ubuntu:18.04

WORKDIR work

ADD ./file.txt /work/file.txt
ADD ./file2.txt /work/file2.txt

CMD ["ls"]
```

さて、`docker-compose up`を実行してみます。すると次のような結果になりました。

```bash
$ docker-compose up
Starting my-apline ... done
Attaching to my-apline
my-apline | file.txt
my-apline exited with code 0
```

出力を見ればわかるように、コンテナ（my-apline）にtest2.txtが含まれていません。

なぜなら今回の`docker-compose up`は、**さきほど作成したコンテナをただ起動しただけだから**です。

その証拠に、コンテナとイメージを確認しても変わりがないことが見てとれます。

```bash
$ docker ps -a     
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
6d14fde119f0        my-alpine-image     "/bin/bash"              10 minutes ago      Exited (0) 10 minutes ago                       my-apline
```

```bash
$ docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
my-alpine-image            latest              ff8e7d96a995        10 minutes ago        64.2MB
```

## どのように`up`すべきだったか

では、どうすればtest2.txtを含んだ、**最新のイメージを使ったコンテナになるのでしょうか。**

正解は、「再度ビルドする」ことを明示する`--build`オプションを使うことです。

```bash
$ docker-compose up --build
Building test
// Stepは省略

Successfully built 7218cdd4f17a
Successfully tagged my-alpine-image:latest
Recreating my-apline ... done
Attaching to my-apline
my-apline | file.txt
my-apline | file2.txt
my-apline exited with code 0
```

イメージもコンテナも新しくなっていることがわかります。

```bash
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
28c26826bf20        my-alpine-image     "/bin/bash"              2 minutes ago       Exited (0) 2 minutes ago                       my-apline
```

```bash
$ docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
my-alpine-image            latest              7218cdd4f17a        About a minute ago   64.2MB
```

## まとめ

まとめると、`docker-compose up`というコマンドは、

* まだイメージが作成されていなければ、イメージを作成して、さらにコンテナを作成・起動する
* すでにコンテナが存在すれば、イメージ・コンテナの再作成は行わず、（停止中の）コンテナを起動するだけ

ということがわかりました。

ちなみにイメージがない状態で`docker-compose up`するとコンソールに、

> Image for service test was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
> （サービステスト用のイメージが存在しなかったためにビルドされました。このイメージを再構築するには `docker-compose build` か `docker-compose up --build` を使う必要があります。）

と出ていたことに気づきました。英語をちゃんと読めばこんなに迷う必要はなかったですね。

似たような箇所でつまづいた人たちの参考になれば幸いです！