Dockerコンテナーの実行時にサービスを自動的に開始するにはどうすればよいですか?


157

MySQLサーバーをコンテナーにインストールするためのDockerfileがあり、それを次のように開始します。

sudo docker run -t -i 09d18b9a12be /bin/bash

しかし、MySQLサービスは自動的に開始されません。手動で(コンテナー内から)実行する必要があります。

service mysql start

dockerコンテナーを実行するときに、MySQLサービスを自動的に開始するにはどうすればよいですか?


1
いいえ、1つの単純なサービスの場合、スーパーバイザは必要ありません。開始ユーザーにとって複雑になります
Larry Cai

8
存在しないファイルにリンクするのではなく、ここにdockerfileをコピーすることをお勧めします
neo112

スーパーバイザーに関するドッカーの記事がここにあります:docs.docker.com/config/containers/multi-service_container && tailコマンドを使用してサービスを機能させましたが、「-cap-add SYS_PTRACE」をドッカーに追加する必要がありましたコマンドを実行します。
Ted Cahall 2018年

回答:


205

まず、あなたに問題がありますDockerfile

RUN service mysql restart && /tmp/setup.sh

Dockerイメージは実行中のプロセスを保存しません。したがって、RUNコマンドはdocker buildフェーズ中にのみ実行され、ビルドが完了すると停止します。代わりに、以下のようなCMDor ENTRYPOINTコマンドを使用してコンテナを起動するときに、コマンドを指定する必要があります。

CMD mysql start

次に、Dockerコンテナーは実行を継続するためのプロセス(最後のコマンド)を必要とします。そうしないと、コンテナーは終了/停止します。したがって、通常のservice mysql startコマンドをDockerfileで直接使用することはできません。

解決

プロセスを実行し続けるには、3つの典型的な方法があります。

  • serviceコマンドを使用し、その後に非終了コマンドを追加するtail -F

    CMD service mysql start && tail -F /var/log/mysql/error.log
    

これは、出力されたログをdockerがアクセスできるようにするため、単一のサービスを実行している場合によく使用されます。

  • または、フォアグラウンドコマンドを使用してこれを実行します

    CMD /usr/bin/mysqld_safe
    

これは、のようなスクリプトがある場合にのみ機能しますmysqld_safe

  • または、スクリプトをにラップして、start.shこれを最後に配置します

    CMD /start.sh
    

これは、コマンドが一連のステップを実行する必要がある場合、やはり/start.sh実行を継続する必要がある場合に最適です。

注意

初心者のsupervisord方にはお勧めできません。正直、やりすぎです。コンテナーには単一のサービス/単一のコマンドを使用する方がはるかに優れています。

ところで、参照のために既存のmysql dockerイメージがないかhttps://registry.hub.docker.comを確認してください


Dockerコンテナーで開始したサービスをどのように再起動しますか?
K-SOの毒性が高まっています。

3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
カイザー

1
MySQLのエラーログを追跡して、データベースが実行中かどうかを判断することはお勧めしません。ほとんどのmysqldセットアップでは、サーバーはsoeエラーから回復し、これを実行する過程でエラーログは閉じられ、その後再び開かれます。私はまた、あなたのしっぽ-Fがすべてまたはいくつかのケースであなたのためにうまくいくかどうかもわかりません。
ブライアンエイカー2016年

理由はわかりませんが、サービススクリプトでは最初のソリューションオプションが適切に機能します。tailを使用しない場合、サービスが開始されていても(少なくともtomcat7サービスでは)失敗します。尾で動作します。どちらの場合も、少なくともSYS_PTRACEを指定してスイッチcap_add(-cap-add SYS_PTRACE for run)を使用する必要があります
zhrist

1
いいえ、stackoverflow.com
Larry Cai

73

あなたDockerfileの最後の行に追加します

ENTRYPOINT service ssh restart && bash

わたしにはできる

そしてこれが結果です:

root@ubuntu:/home/vagrant/docker/add# docker run -i -t ubuntu
 * Restarting OpenBSD Secure Shell server sshd   [ OK ]                                                                      
root@dccc354e422e:~# service ssh status
 * sshd is running

2
これはいいことですが、この方法ではコンテナーを切り離すことはできないと思います。
mdob

1
これは私にとってはうまくいきました。Nginx 1.8を自動起動するのに問題がありました。以下を追加すると便利です。RUNecho "daemon off;" >> /etc/nginx/nginx.conf RUN ln -sf / dev / stdout /var/log/nginx/access.log RUN ln -sf / dev / stderr /var/log/nginx/error.log
Lionel Morrison

1
このソリューションには欠点がありますか?
srph 2016年

2
サービスを正常に停止する場合、Bashを最終的に起動することはお勧めできません。この方法では、Docker contaienrを停止しdocker stopたり、docker restart正常に停止したりすることはできません。
Mohammed Noureldin 2017年

私はドッカーのイメージを作成するためにパッカーに取り組んでいました、そしてこれはパッカーファイルのconaitnerで私の問題を修正するようです。"changes":["ENTRYPOINT service nginx start && / bin / bash"]
karthik101

8

シンプル!dockerfileの最後に追加します。

ENTRYPOINT service mysql start && /bin/bash

これが私の現在のDockerコンテナの問題を解決する最良の答えです:Docker version 18.09.7, build 2d0083d&& /bin/bashサービスなしですぐに停止します
Long

7

それを行うには、私がいつもより読みやすいと思っている別の方法があります。

実行時にrabbitmqとmongodbを起動したいとすると、次のようになりますCMD

CMD /etc/init.d/rabbitmq-server start && \
    /etc/init.d/mongod start

あなたは一つだけ持つことができますので、CMDあたりDockerfileトリックをしてすべての命令を連結することで&&、次に使う\新しい行を開始するには、各コマンドのために。

それらの多くに追加してしまう場合は、すべてのコマンドをスクリプトファイルに入れ、@ larry-caiが提案するように開始することをお勧めします。

CMD /start.sh

3

私の場合、Apache2によって提供されるPHP Webアプリケーションが、MYSQLバックエンドデータベースに接続するdockerコンテナー内にあります。Larry Caiのソリューションは、小さな変更で機能しました。entrypoint.shサービスを管理するファイルを作成しました。entrypoint.shコンテナーの起動時に実行するコマンドが複数あるときにを作成すると、Dockerをブートストラップするためのよりクリーンな方法になると思います。

#!/bin/sh

set -e

echo "Starting the mysql daemon"
service mysql start

echo "navigating to volume /var/www"
cd /var/www
echo "Creating soft link"
ln -s /opt/mysite mysite

a2enmod headers
service apache2 restart

a2ensite mysite.conf
a2dissite 000-default.conf
service apache2 reload

if [ -z "$1" ]
then
    exec "/usr/sbin/apache2 -D -foreground"
else
    exec "$1"
fi

Dockerfileの横に置くだけです。次に、Dockerfileに、このファイルを目的の場所にコピーする手順を記述します。次に、ENTRYPOINT ['your location']命令をスクリプトファイルにポイントします。ただし、スクリプトの実行権限を設定することを忘れないでください。COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]。この例では、エントリーポイントをDockerコンテナーのルートディレクトリにコピーしました。
Doomsbuster氏、2018年

Dockerfileはどこにありますか?
Viktor

3

sshサービスを自動的に開始したいのですが、同じ問題があります。私はそれを見つけました

/etc/init.d/ssh start
〜/ .bashrc
それを解決できますが、bashで開くことができるのはあなただけです。


1

次のコードを/root/.bashrcに追加して、コードを1回だけ実行します。

このスクリプトを実行する前に、コンテナをイメージにコミットしてください。そうしないと、「docker_services」ファイルがイメージ内に作成され、サービスは実行されません。

if [ ! -e /var/run/docker_services ]; then
    echo "Starting services"
    service mysql start
    service ssh start
    service nginx start
    touch /var/run/docker_services
fi

1

dockerコンテナーが実行されるたびに、MySQLサービスを自動的に開始する方法を次に示します。

私の場合、MySQLだけでなくPHP、Nginx、Memcachedも実行する必要があります

Dockerfileに次の行があります

RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 3306
CMD service mysql start && service php-fpm start && nginx -g 'daemon off;' && service memcached start && bash

&& bashを追加すると、コンテナー内でNginx、MySQL、PHP、Memcachedが実行され続けます。


1

これは機能しません CMD service mysql start && /bin/bash

これは機能しません CMD service mysql start ; /bin/bash ;

-インタラクティブモードはフォアグラウンドをサポートしないと思います。

これはうまくいきます! CMD service nginx start ; while true ; do sleep 100; done;

これはうまくいきます! CMD service nginx start && tail -F /var/log/nginx/access.log

docker run -p 80:80 nginx_bashコマンドパラメータなしで使用する必要があることに注意してください。


0

Docker Webサイトの次のドキュメントは、DockerコンテナーにSSHサービスを実装する方法を示しています。それはあなたのサービスに簡単に適応できるはずです:

この質問のバリエーションもここで尋ねられました:


nsenterツールは、SSHサーバーのインストールを必要とせずにコンテナーに入る別のアプローチです:github.com/jpetazzo/nsenter。ただし、このアプローチではDockerホストへのアクセスが必要です(通常はSSHアクセスで十分です)。
Fabien Balageas、2015年

リンクdocs.docker.com/sorry/#/examples/running_ssh_serviceは機能しません。更新して頂けますか?
Ankur

0
docker export -o <nameOfContainer>.tar <nameOfContainer>

docker pruneを使用して既存のコンテナーを削除する必要があるかもしれません...

必要な変更を加えてインポート:

cat <nameOfContainer>.tar | docker import -c "ENTRYPOINT service mysql start && /bin/bash" - <nameOfContainer>

たとえば、常に再起動オプションを指定してコンテナーを実行し、ホスト/デーモンのリサイクル後にコンテナーが自動的に再開されるようにします。

docker run -d -t -i --restart always --name <nameOfContainer> <nameOfContainer> /bin/bash

補足:私の意見では、コンテナーをできるだけクリーンにしてcronサービスのみを開始し、対応するチェック/監視スクリプトを使用してcrontabまたはcron.hourly、.dailyなどを変更するだけです。理由は1つのデーモンのみに依存しているため、変更の場合は、起動時に開始するサービスを追跡するのではなく、ansibleまたはpuppetを使用してcronスクリプトを再配布する方が簡単です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.