こんばんは。
毎日暑いですね…7月ってこんなだったっけ…。
今回はコンテナの中のJenkinsを利用してホストのDockerを操作してみます。
そもそもなんでそんなことがしたいか
ちょっとアクロバティックなのでなんでそんなことしたいの?というお話です。
例えばバッチプログラムをコンテナ内で動かしたい場合、
・コンテナを立ち上げたままにしておいてcron等を使ってスケジュール実行する
・ホスト側のcronやジョブ管理システムを使ってコンテナを実行時に立ち上げる
という方法が思い浮かびます。
対象のコンテナは実行時にだけ立ち上がって、実行が終わったら止まっているのがリソース的に良さそうです。
一方でせっかくDockerを使うならホスト側の環境はあまり触りたくないです。
じゃあジョブ管理システムをコンテナで立ち上げてしまえばいいじゃないか!となるわけですが、そうなるとどうやってそこからホストのDockerを操作するんだっていう話になります。
DooD
そこでDockerコンテナの中からホストのコンテナを操作する、DooD(Docker outside of Docker)という技術を使います。
ちなみにDockerコンテナの中にさらにDockerを立ち上げるのをDinD(Docker in Docker)というらしいです。
やっていることとしてはホストのDockerデーモンのソケットファイルをコンテナ内にマウントするというシンプルな方法です。
プロセスの通信に使うインタフェースをそのままコンテナ内に渡してしまうという感じでしょうか。
UNIXドメインソケット - Wikipedia
で、せっかくコンテナを建てるなら何かジョブ管理システムを入れましょうということで、Jenkinsを入れてみます。もちろん好きなものでOK。
こうするとHTTPでのトリガとかもできるようになりますね(実際には今回はnginxの裏側に置きますが)
というわけで
Dockerの設定ファイルを書きます。
まずDockerfile。
FROM jenkins/jenkins:lts USER root # ベースディレクトリの所有者をjenkinsに RUN chown -R jenkins:jenkins /var/jenkins_home # dockerのインストール RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && rm get-docker.sh USER jenkins
で、docker-compose.yml。
web_networkに参加させてますが、これはnginxがいるネットワークです。
Docker ComposeでMySQLとnginxのコンテナを立てる - 白猫のメモ帳
version: '3.8' services: jenkins: build: context: ./ container_name: jenkins group_add: - docker environment: TZ: "Asia/Tokyo" JENKINS_OPTS: "--prefix=/jenkins" JAVA_OPTS: "-Xms512m -Xmx1024m" volumes: - ./jenkins_home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock networks: - web_network networks: web_network: external: true
ポイントは/var/run/docker.sockをマウントしていることです。
これがソケットファイルですね。
逆に言うとこいつをマウントさえしてあげればDooDは完成です。
JENKINS_OPTS: "--prefix=/jenkins"はnginxの裏側に置くためにパスにプレフィクスをつけています。
なので、default.confはこんな感じで書きます。
(略) location /jenkins/ { proxy_pass http://jenkins:8080/jenkins/; } (略)
今回はJenkinsの設定とかがメインじゃないのでそこらへんは省略。
jobを作ってこんな感じにすると、指定したコンテナのrestartとかできます。
コンテナ便利ですね
やっぱりDockerを使っていると、Dockerの外の世界を散らかしたなくない気持ちになります。
せっかくなのできれいに運用したいですね。