47
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

dockerで初回起動時のみ特定の処理を行うヘルパースクリプト(docker-entrypoint.sh)

Last updated at Posted at 2020-02-21

はじめに

docker run とか docker-compose up -d とかの 初回起動時のみ 処理したいことがある時はどうすればいいんだろう?
docker restart とか docker-compose restart とか systemctl restart docker の時には動いてほしくないんだ。

やってみた結果 mariadb + zabbix で初回起動時のみ、構成用の .sql を流し込む。という動作ができるようになりました。
日本人にやさしそうなMIRACLE ZBXをdocker-composeでまとめた

経緯

zabbix の docker-compose.yml を作成しようとしたら、 dnf でインストールした後に特定ディレクトリにある .sql を MariaDB に食わせる必要がありました。
ビルド時には DB が起動してないので、流し込めない。
MariaDB の初回起動時の .sql ファイル流し込みだと、現時点の .sql は準備できるけど、zabbix のアップデートに追従できない。
rc.local 起動時のスクリプトで実行しようとしたら、ホスト機やサービスの再起動のたびに動いてしまう。

どうしよう。

動作の概要

ということで、MariaDB とか mysql とか postgresql とかの公式イメージでやってる、初回起動時の .sql 流し込みのアイデアを拝借しました。

考え方は以下のとおり

  1. Dockerfileの ENTRYPOINTdocker-entrypoint.sh というヘルパースクリプトを呼び出す。
  2. Dockerfileの CMD"/sbin/init" を書き込んでヘルパースクリプトに引数として渡す。
  3. ヘルパースクリプトは判別用のディレクトリの有無を確認し、
  4. ディレクトリが無い場合 -> 作成する
  5. ディレクトリが有る場合 -> なにもしない
  6. ヘルパースクリプトは前段の処理のあと、自身を起動した際の引数の文字列(= /sbin/init)を実行する

これで、コンテナを初回起動した場合のみ、特定の処理を挟み込むことができる。

検証

ホントにできるか検証します。

ファイルの準備

以下のようにファイルを準備します。

sample
|-- Dockerfile
|-- docker-compose.yml
`-- docker-entrypoint.sh
/root/sample/Dockerfile
FROM centos:centos8
COPY docker-entrypoint.sh /tmp
ENTRYPOINT ["/tmp/docker-entrypoint.sh"]
CMD [ "/sbin/init" ]
/root/sample/docker-compose.yml
version: '3'

services:
  sample:
    build: ./
    container_name: sample
    hostname: sample
    restart: always
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp:unconfined
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    environment:
      TZ: 'Asia/Tokyo'
/root/sample/docker-entrypoint.sh
#!/bin/sh

if [ ! -d "/tmp/check" ]; then
  mkdir /tmp/check
  echo `date` > /tmp/check/first_`date +%Y%m%d_%H%M%S`
else
  echo `date` > /tmp/check/second_`date +%Y%m%d_%H%M%S`
fi

exec "$@"

動作確認

ビルド&初回起動 -> コンテナリスタート -> コンテナリスタート
としたとき docker-entrypoint.sh で作成されるダミーファイルの状況を追ってみます。


# docker-compose up --build -d ; docker exec -it sample ls -1 /tmp/check
Creating network "sample_default" with the default driver
Building sample
Step 1/4 : FROM centos:centos8
 ---> 470671670cac
Step 2/4 : COPY docker-entrypoint.sh /tmp
 ---> 65969481a77a
Step 3/4 : ENTRYPOINT ["/tmp/docker-entrypoint.sh"]
 ---> Running in faa635fbdd2c
Removing intermediate container faa635fbdd2c
 ---> f0fd6de7dd9f
Step 4/4 : CMD [ "/sbin/init" ]
 ---> Running in 4d8a074a1da4
Removing intermediate container 4d8a074a1da4
 ---> cae2d8667ff6
Successfully built cae2d8667ff6
Successfully tagged sample_sample:latest
Creating sample ... done
first_20200220_213008
(↑初回起動時処理のファイルが作成されている)

# docker-compose restart ; docker exec -it sample ls -1 /tmp/check
Restarting sample ... done
first_20200220_213008
second_20200220_213025
(↑初回起動時ではない処理のファイルが作成されている)

# docker-compose restart ; docker exec -it sample ls -1 /tmp/check
Restarting sample ... done
first_20200220_213008
second_20200220_213025
second_20200220_213042
(↑初回起動時ではない処理のファイルが作成されている)

ということで、無事にそれっぽいことができました。
ここに zabbix をインストールしたときに作成される .sql を流し込めば、全自動で処理ができそうです。

もちろん、 /sbin/init の動作もきちんとできていました。

# docker exec -it sample bash
(これでコンテナにログイン)

[root@sample /]# systemctl status
● sample
    State: running
     Jobs: 0 queued
   Failed: 0 units
    Since: Thu 2020-02-20 21:30:58 JST; 3min 14s ago
   CGroup: /docker/f8a80d798e046e22c343f95b4fc9c9b8d623d0ef97ba39becfdc1debe21a0b35
           tq83 bash
           tq96 systemctl status
           tq97 less
           tqinit.scope
           x mq1 /sbin/init
           mqsystem.slice
             tqsystemd-journald.service
             x mq22 /usr/lib/systemd/systemd-journald
             mqdbus.service
               mq36 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
[root@sample /]#

うん、大丈夫そう。

さいごに

ん、よく考えたら、同じようなことを rc.local でやればよかったのかも。
Dockerfile のことを少し知れたので、勉強にはなりましたが。

"ヘルパースクリプト"という言葉自体、あまり使われていないのですね
実は全然イケてない方法だったり?使い方まちがってたりして?と、ちょっとビクビクします
もしくは当たり前すぎんだよ!てな感じでしょうか。。。

Screenshot from Gyazo

参考

http://docs.docker.jp/engine/reference/run.html
https://github.com/docker-library/mysql/tree/master/8.0

47
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?