Docker Composeでdriver failed programming external connectivity on endpointとなった時の対応方法

- 環境(Dockerホスト)
    - CentOS Linux release 7.6.1810 (Core)
    - Docker version 18.09.6, build 481bc77156
    - docker-compose version 1.24.0, build 0aa59064

# 事象 : Dockerでコンテナを作ろうとしたら怒られた

```bash
$ docker-compose up -d --no-recreate --build
# 省略
ERROR: for container03  Cannot start service container03: driver failed programming external connectivity on endpoint container03 (...): Bind for 0.0.0.0:80 failed: port is already allocated
```

# 原因1 : 他のコンテナとポートがかぶっているから
エラーメッセージの後ろのほうに書いてある

```bash
$ docker ps
CONTAINER ID        IMAGE     COMMAND             CREATED             STATUS              PORTS                    NAMES
abcde1234567        image01   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:8080->8080/tcp   container01
1234567890ab        image02   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:80->8081/tcp     container02
```

## 対応 : 使われていないポートに変更する
`{ホストのポート番号}:{コンテナのポート番号}`となるので「ホストのポート番号」を変更する

```yml:docker-compose.yml
    ports:
      - "8082:8080"
```

### コンテナを作り直すときは、作成に失敗したコンテナを削除してから作り直す
作成に失敗したコンテナを削除してから作り直さないと「原因2」の状態になる。
[自分のコンテナだけ作り直す方法 - Qiita](https://qiita.com/ponsuke0531/items/960b1da7e1656c5d6ce3)

```bash
# 停止しているコンテナも含めて全コンテナを表示して「作成に失敗したコンテナ」のCONTAINER IDを確認する
$ docker ps -a
# 「作成に失敗したコンテナ」を削除する
$ docker rm {「作成に失敗したコンテナ」のCONTAINER ID}
# コンテナを作り直す
$ docker-compose up -d --no-recreate --build {コンテナの名前}
```

# 原因2 : 作成に失敗したコンテナが残っておりそのコンテナで作り直されてしまっているから
原因1の対応をした後に発生する。

せっかくポートを重複しないように`docker-compose.yml`に設定しても
ポート変更前の作成に失敗したコンテナが残っており
そのコンテナで作り直されてしまっているので
ポートが変更されずエラーになっている。

```bash:事象
# ポートが他のコンテナと重複しないように変更する
$ vi docker-compose.yml

# ポートを変更したはずなのに「ポートが重複している」とエラーになる
$ docker-compose up -d --no-recreate --build container03
# 省略
Successfully tagged image03:latest
Starting container03 ... error

ERROR: for container03  Cannot start service container03: driver failed programming external connectivity on endpoint container03 (...): Bind for 0.0.0.0:80 failed: port is already allocated

ERROR: for container03  Cannot start service container03: driver failed programming external connectivity on endpoint container03 (...): Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
```

## 対応 : 作成に失敗したコンテナを削除してから作り直す
[ps &mdash; Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/reference/commandline/ps.html)
[Dockerイメージとコンテナの削除方法](https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae)

```bash
# 「停止しているコンテナも含めて全コンテナを表示する」と作成に失敗したコンテナが停止状態で存在していた
$ docker ps -a
CONTAINER ID        IMAGE     COMMAND             CREATED             STATUS              PORTS                    NAMES
e2be66d8de53        image03   "/usr/sbin/init"    37 minutes ago      Created                                      container03
abcde1234567        image01   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:8080->8080/tcp   container01
1234567890ab        image02   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:80->8081/tcp     container02

# 作成に失敗したコンテナを削除する
$ docker rm e2be66d8de53
e2be66d8de53

# 削除されたことを確認する
$ docker ps -a
CONTAINER ID        IMAGE     COMMAND             CREATED             STATUS              PORTS                    NAMES
abcde1234567        image01   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:8080->8080/tcp   container01
1234567890ab        image02   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:80->8081/tcp     container02

# コンテナを再度作る
$ docker-compose up -d --no-recreate --build container03
# 省略
Successfully tagged image03:latest
Creating container03 ... done

# 作成されたか確認する
$ docker ps -a
CONTAINER ID        IMAGE     COMMAND             CREATED             STATUS              PORTS                    NAMES
514fdac2fb69        image03   "/usr/sbin/init"    5 minutes ago       Up 5 minutes        0.0.0.0:8082->8080/tcp   container03
abcde1234567        image01   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:8080->8080/tcp   container01
1234567890ab        image02   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:80->8081/tcp     container02

# ちゃんと停止せずに作成された
$ docker ps
CONTAINER ID        IMAGE     COMMAND             CREATED             STATUS              PORTS                    NAMES
514fdac2fb69        image03   "/usr/sbin/init"    6 minutes ago       Up 5 minutes        0.0.0.0:8084->3389/tcp   container03
abcde1234567        image01   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:8080->8080/tcp   container01
1234567890ab        image02   "/usr/sbin/init"    2 weeks ago         Up 40 minutes       0.0.0.0:80->8081/tcp     container02
```