docker-compose メモ

個人的なメモです。つい忘れてしまうので。。。

# Dockerのイメージを完全に削除

```sh
#!/bin/bash

docker system prune -a --volumes
docker rm -vf $(docker ps -a -q)
docker rmi -f $(docker images -a -q)
docker images

```

# Dockerの更新

```sh
#!/bin/bash

sudo docker-compose stop
sudo docker-compose pull
sudo docker-compose up -d
```

# docker-composeコマンドを実行すると、固まってしまう場合

なんかdocker-composeとPythonの相性の問題らしい。
https://github.com/docker/compose/issues/6678#issuecomment-494402189

コメントに書いてあった`haveged`をインストールしたら解決した。

```sh
$> sudo apt-get install haveged
```

止まっていると見せかけて動いているかもｗ

```sh
docker-compose --verbose up
```

# docker-compose.ymlを分ける

開発のときと、実行時と docker-compose.ymlファイルを分けたかった。

```sh
$> docker-compose -f docker-compose-dev.yml build --build-arg NODE_ENV=development
```

# DockerFileを指定する

開発のときと、実行時と DockerFileファイルを分けたかった。

```yml
version: '3'
services:
  myapp:
    build:
     context: ./myapp
     dockerfile: Dockerfile-dev
```

# 引数を渡す


```sh
$> docker-compose -f docker-compose.yml build --build-arg NODE_ENV=production
```

**Dockerfile**

```
# default: development  でも productionに置き換えられる
ARG NODE_ENV=development
ENV NODE_ENV=$NODE_ENV
```

# ENVを定義する

```yml
version: '3'
services:
  myapp:
    environment:
      - NODE_ENV=production-local
```

# サーバーが起動したときに実行

```yml
version: '3'
services:
  myapp:
    restart: always
```


# サーバーではrestart='always'、macではrestart='no'

Bashのデフォルト値を使えば良い。

```
version: '3'
services:
  myapp:
    ...
    restart: ${DOCKER_RESTART:-always}
````

環境変数に `DOCKER_RESTART`の値があれば、それに従う。なければ`always`が適用される。
`DOCKER_RESTART` は　`.bashrc`とか`.bash_profile`に定義すれば良い

```
export DOCKER_RESTART="no" 
```

# restart='always'をrestart='no'にする

```
$> docker update --restart="no" $(docker ps -aq)
```

# コマンドを実行

```yml
version: '3'
services:
  redis:
    image: redis:5.0.5-alpine
    command: ["redis-server"]
```

# Redisイメージを使ったとき、redis-cliを使う

```yml
version: '3'
services:
  redis:
    image: redis:5.0.5-alpine
    command: ["redis-server"]
    container_name: "redis"
    expose:
      - 6379
    hostname: redis
    networks:
      - proxy_net
    volumes:
      - ./data/redis:/data
    restart: always
```

```sh
$> docker exec -it redis redis-cli
```

# Redisイメージを使ったとき、別のコンテナからredis-cliを使って接続

```yml
version: '3'
services:
  redis:
    image: redis:5.0.5-alpine
    command: ["redis-server"]
    container_name: "redis"
    expose:
      - 6379
    hostname: redis
    networks:
      - proxy_net
    volumes:
      - ./data/redis:/data
    restart: always

  myapp:
    links:
      - redis
    environment:
      - REDIS_URL=redis://redis
    build:
      context: ./myapp
    container_name: "myapp"
    #volumes:
    #  - ./myapp/src:/frontend/src
    working_dir: /myapp
    tty: true
    ports:
      - 4002:4002
    restart: always
    networks:
      - proxy_net
```

Dockerfile

```
FROM node:10.12.0-alpine


RUN apk --update add redis
```

Shell

```sh
$> docker exec -it myapp sh

#myapp> redis-cli -h redis
```

# 無制限に使えるDockerコンテナレポジトリ

~~https://treescale.com/~~

~~UIはイマイチだけど、**「無料で」「無制限に」「public/private Dockerコンテナ・レポジトリを作れる」**嬉しいサービス。
もうみんなこれでいいじゃん。~~

(update) treescale.comがある日、突然ダウンして困ったことがあったので、別のレポジトリサービス https://cloud.canister.io/ に移動。
こっちのが安定していますし、UIがマトモに使える。


このサービスのおかげで、admin, frontendなど、目的ごとにコンテナが作れるのが嬉しい。

使い方は簡単。サインインしたあとは、treescale.comでコンテナレポジトリを作る。

で、docker-compose.ymlにイメージ名を指定する。

```yml

version: '3'
services:
  myapp:
    build:
      context: ./myapp
    image: repo.treescale.com/myaccount/myapp
    container_name: "myapp"
```

ビルド

```
$> docker-compose build
```

ログインとpush

```
~# docker login repo.treescale.com
username: [your TreeScale Username]
password: [TreeScale password]

~# docker push repo.treescale.com/myaccount/myapp

```

pullとかpush

```
~# docker pull repo.treescale.com/[username]/[image name]:[tag]
~# docker push repo.treescale.com/[username]/[image name]:[tag]
```

# https-portalを複数のdocker-compose.ymlで共有する

1つのサーバーで、`https-portal`を全部共有したい。
でもWebアプリごとに別々の`docker-compose.yml`を作りたい。
そうゆうときはネットワークを作れば良い。

**https-portal の docker-compose.yml**

```yml
version: '3.5'
services:
  https-portal:
    container_name: "https-portal"
    image: steveltn/https-portal:1
    ports:
      - 80:80
      - 443:443
    restart: 'always'
    environment:
      DOMAINS: >-
        myapp1.mydomain.com -> http://dockerhost:3000,
        myapp2.mydomain.com -> http://dockerhost:4000
      STAGE: "${DOCKER_STAGE}"
    networks:
      - proxy_network

networks:
  proxy_network:
    external:
      name: proxy_network
```

**myapp1 の docker-compose.yml**

```yml
version: '3.5'
services:
  myapp1:
    container_name: "myapp1"
    build: .
    restart: "${DOCKER_STAGE}"
    ports:
      - "3000:3000"
    networks:
      - common-network

networks:
  common-network:
    name: proxy_network
```

# DockerのApacheが起動しない

まさにこんなログ。

```
[root@newhope sergio]# docker logs sharp_shockley 
httpd (pid 1) already running
httpd (pid 1) already running
httpd (pid 1) already running
httpd (pid 1) already running
```

どうやら原因は `/run/apache2/apache2.pid` にファイルが残ってしまっていることらしい。
なぜそうなったのかはよく分からない。

とりあえず、このコマンドで実行環境を削除してくれるそうなので、これで解決した。

```
#> docker-compose down
```

詳しくは[StackOverflow - docker container won't start because an existing pid file](https://stackoverflow.com/questions/28654076/docker-container-wont-start-because-an-existing-pid-file) を参照。

(追記)

最終的には、シェルスクリプトを1つ作って、コンテナの起動時にファイルを強制的に削除するようにして解決

```Dockerfile

COPY ./startup.sh /root/startup.sh
COPY ./mpm_prefork.conf /etc/apache2/mods-enabled/mpm_prefork.conf

RUN chmod +x /root/startup.sh

CMD ["/root/startup.sh"]
```

```startup.sh
#!/bin/sh

rm -f /run/apache2/apache2.pid
apachectl -DFOREGROUND
```


# Dockerコンテナ内からホストにアクセス

Docker v20から可能。

https://stackoverflow.com/a/43541732/697856

```docker-compose.yml
extra_hosts:
- "host.docker.internal:host-gateway"
```

# Dockerコンテナのためのwatchdog

Dockerコンテナがダウンしたら自動的に再起動してくれるDockerコンテナ
https://github.com/buanet/docker.watchdog