Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@naomichi-y

Docker環境でRails停止時にExit code 1が発生する

問題

Docker上でRails (Puma) を実行中に docker stop でコンテナを停止させようとするとExit 1 (SIGHUP) が発生します。
ECSやKubernetesを利用している場合、コンテナが正しく終了せず、予期しない問題を引き起こす可能性があります。

% docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                      PORTS               NAMES
xxx        rails                      "bundle exec rails s…"   44 seconds ago      Exited (1) 3 seconds ago                        api
xxx

原因

俗に言う「PID 1問題1」が原因。PID 1はinitプロセスと呼ばれるもので、システム起動時にカーネルによって呼び出される特別なプロセスです。initプロセスはシグナルハンドリングや子プロセスの生成、ゾンビプロセスの削除などを行います。
今回はRails (2)を起動した際にPID 1が使われてしまい、シグナルを正しくハンドリングできないといった問題が発生していました。

# コンテナ上でtopコマンドを実行した結果
  PID USER      PR  NI    VIRT    RES  %CPU  %MEM     TIME+ S COMMAND
    1 root      20   0    2.2m   1.5m   0.0   0.1   0:00.02 S /bin/bash /bin/docker-entrypoint.sh bundle exec rails s -b 0.0.0.

プロセスを見ると、PID 1でRailsが起動していることが分かります。

対策

tinidumb-init といったプログラムを使うことで、PID 1の子プロセスとしてアプリケーションを起動することが可能となります。
docker-compose 3.7以降が利用可能であれば、docker-compose.ymlinit パラメータを付けることで問題を回避することができます (3)。

# Railsがinitプロセスの子プロセスとして起動する
PID USER      PR  NI    VIRT    RES  %CPU  %MEM     TIME+ S COMMAND
1 root      20   0    1.0m   0.0m   0.0   0.0   0:00.03 S /sbin/docker-init -- /bin/docker-entrypoint.sh bundle exec rails s -b 0.0.0.0
6 root      20   0    2.2m   1.5m   0.0   0.1   0:00.00 S  `- /bin/bash /bin/docker-entrypoint.sh bundle exec rails s -b 0.0.0.0

docker-compose down 実行後にプロセスを見ると、143 (SIGTERM) でコンテナが停止しています。

% docker-compose ps
          Name                         Command                State     Ports
-----------------------------------------------------------------------------
api                 /bin/docker-entrypoint.sh  ...   Exit 143

ECSを利用している場合

タスク定義に initProcessEnabled: true (4) を追加します。initProcessEnableddocker run--init に相当します。

Kubernetesを利用している場合

tiniなどの軽量initを使う方法もありますが、Kubernetes 1.17からは Share Process Namespace (5) を使うことで問題を回避できるようです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What are the problem?