【Docker】初めてdocker-composeでbuild+app runまでする構成を組もうとして挫折した

Go + VueなアプリをDockerでビルド用コンテナ+稼働用コンテナ+docker-composeするまでの過程で ハマったところをつらつらとログした記事。

世には素晴らしい日本語記事がいっぱいでているが、 今更やってみたの一例として、誰かの参考になればというモチベで進行。

環境

項目 内容
ホストOS Ubuntu 16.04
Docker 17.05.0-ce
Docker Compose 1.22.0
コンテナOS alpine 3.9
Golang 1.11.5
nodejs 10.14.2
vuecli 2.9.6

とりあえずできたやつ

https://github.com/pakuyuya/dbsql-meta-viewer/tree/master/docker

  • dep ensure + go build、vuecliで生成したテンプレートをnpm run build してパッケージング、ビルドしたコンテナ自身にデプロイして動かす簡単なスクリプト

セットアップ

Install Docker/Docker-compose to host server

https://docs.docker.com/install/ http://docs.docker.jp/compose/install.html

ビルドコンテナ

流れ

  • コンテナに必要なパッケージをインストールして環境変数もいい感じに初期化したイメージを、Dockerfileからビルドする
  • ビルドするときエントリポイントにシェルを仕込んでおき、コンテナを run したら git clone -> build のあと、コンテナ内 /var/distにビルド後のモジュールを出力。
  • コンテナをrunするときに/var/distに任意のディレクトリをマウント、ビルド結果を受け取る。

ハマり1:ARGには複数の値を指定できない

ビルドするときにパラメータガンガン渡せばいーじゃんと思ったけどなんかダメだそう。

下記は×

# Dockefile
FROM alpine:3.9

ARG REPOSITORY=https://github.com/pakuyuya/dbsql-meta-viewer.git \
        ENVTARGET=production

代替策

2019/02/27

全然できた なんで悩んでたんだ・・

ハマリ2:ashで、シェルを呼んだ先のシェルを呼んだ先のシェルを呼ぶことができない

alpineの標準シェル

docker/build/Dockefile

FROM  alpine:3.9

ENV REPOSITORY=https://github.com/pakuyuya/dbsql-meta-viewer.git \
        # ... 省略 ...

ADD ./entrypoint.sh /
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

docker/build/entrypoint.sh

#!/bin/sh

git clone ${REPOSITORY} /
cd /dbsql-meta-viewer

/bin/sh ./build.sh

build.sh

#!/bin/sh

/bin/sh ./client/build.sh # ここで file not found

対策として、シェルの呼び出し階層を泣く泣く削減した。

アプリケーションコンテナ

やりたかったこと

  • build コンテナを runして、完了したらappコンテナがmountしたvolumeからアプリを受け取ってrunするはずだった

ハマり3:docker-composeの依存関係解決が貧弱

Docker Composeにはコンテナの起動順序を制御するオプションがいくつかあるが、プロセス間のシグナルな同期はサポートしていない。

  • depends_on
    • 依存するコンテナのimagesからのコンテナへマウントを待ってから、自身のコンテナのマウントを始める。runが終わるのは待たない。
  • deploy関連コンフィグ
    • update-config: delay などの微妙に使えそうな設定がある。
    • docker stack deployなどを使ったswarm modeでのみ有効になるらしく、docker-compose up や run では無視されるらしい。

結局のところビルドコンテナとアプリコンテナを泣く泣く統合することで解決したが、 シグナル制御や、volumesを共有して wait for file するのがなんだかんだいって便利なのかもしれない。

(ググって見つけた)