25
12

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環境でRails停止時にExit code 1が発生する

Last updated at Posted at 2020-09-13

問題

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) を使うことで問題を回避できるようです。

  1. Docker and the PID 1 zombie reaping problem

  2. Puma returns exit code 1 in container when received SIGTERM

  3. Compose ファイル バージョン 3 リファレンス - init

  4. AWS::ECS::TaskDefinition LinuxParameters

  5. Share Process Namespace between Containers in a Pod

25
12
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
25
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?