Edited at

サーバ起動時に任意のスクリプトを実行する(dockerコンテナを起動する)

More than 1 year has passed since last update.


結論

/etc/rc.local に起動したいスクリプトを実行するように記述すれば任意のスクリプトを実行することができます。


/etc/rc.local

#!/bin/sh

#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local
# 任意のコマンドを追加
sh /home/developer/sh/startup.sh


※この際に CentOS 7 などのsystemd系を使用しているOSであれば /etc/rc.local に実行権限が必要なようです。


背景

開発環境のコスト削減のため使用していないであろう深夜帯の時間は開発環境のサーバを stop するようになった。

その際に必要なサービスの自動起動の設定はしていたが、docker を使って開発しているため docker コンテナのほうの自動起動の設定はしていなかった。また docker の自動起動設定のオプションはあえて使用していない。理由としては、複数サービスを開発している際に現在開発していないものについては自動で起動する必要がないためである。また、docker コンテナは基本的に単体で使っておらず、docker-compose を使っているものとする。


準備

docker-compose のコマンドを直接実行するのは面倒なので、Makefile を書いている。具体的には docker-compose.yml がある階層と同じ階層に下記のようなファイルを設置している。


Makefile

.PHONY: up down

up:
docker-compose up -d --build

down:
docker-compose down


これを手動で直接実行する場合は

$ make up

-> docker-compose up -d --build が実行され docker コンテナが立ち上がる
$ make down
-> docker-compose down が実行され docker コンテナが停止する

自動起動設定に追加するためのスクリプトを用意する


/home/developer/sh/startup.sh

#!/bin/bash

PARENT_DIR=$(cd $(dirname $0);cd ..;pwd)
src=/home/developer/src

echo "$(date +"%Y/%m/%d %H:%M:%S") run startup.sh" >> ${PARENT_DIR}/run.log

# 起動しておきたいものだけ登録する (並列実行)
make -C ${src}/service1 up 1> /dev/null 2>> ${PARENT_DIR}/error.log &
make -C ${src}/service2 up 1> /dev/null 2>> ${PARENT_DIR}/error.log &
make -C ${src}/service3 up 1> /dev/null 2>> ${PARENT_DIR}/error.log &

# 並列実行を待ち合わせる
wait
echo
"$(date +"%Y/%m/%d %H:%M:%S") complete startup.sh" >> ${PARENT_DIR}/run.log


これを任意の場所に設置しておく。これを手動で実行すればもちろん docker コンテナが立ち上がることを確認しておくとよい。


自動起動設定

linux には自動起動用の設定ファイルとして /etc/rc.local があり、ここに任意のコマンドを書き込んでおくことで起動時に実行させることが可能である。


/etc/rc.local

#!/bin/sh

#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local
# 先ほど設置したスクリプトを実行
sh /home/developer/sh/startup.sh


ちなみに CentOS 7 からは init.d 系から systemd 系に変わったため動かないという記事があるようですが、実行権限を付与して書いておけばちゃんと動くようです。


/usr/lib/systemd/system/rc-local.service

#  This file is part of systemd.

#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.d/rc.local is executable.
[Unit]
Description=/etc/rc.d/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.d/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.d/rc.local start
TimeoutSec=0
RemainAfterExit=yes


ちゃんと systemd 側で起動時用の設定が書かれており、/etc/rc.d/rc.local においておけば使えるよ、正し実行可能でないといけないよという旨が書かれていました。


感想

自動起動の設定等調べたことがなかったので最悪crontabで何とかしようと思っていたのですが、調べてみると以外と手軽に使えて便利そうですね。