web-dev-qa-db-ja.com

Railsサーバーは、新しく開いたdockerコンテナーでまだ実行中です

RailsプロジェクトをDockerを使用してデプロイしたいので、Docker-Composeを使用します。しかし、奇妙なエラーメッセージが表示されます。docker-compose up Railsを使用したWebコンテナ)

web_1 | => Booting Puma web_1 | => Rails 4.2.4 application starting in production on http://0.0.0.0:3000 web_1 | => RunRailsサーバー-hfor more startup options web_1 | => Ctrl-C to shutdown server web_1 | A server is already running. Check /usr/src/app/tmp/pids/server.pid. web_1 | Exitingだからdocker-composeを実行するたびに、前のコンテナではなく新しいコンテナが起動するため、このメッセージが表示される理由を理解できません。これらを削除する場合でもserver.pidこのコンテナが実行されていないため、私はそれを行うことができません。

私のdocker-compose.ymlファイル

web:
  dockerfile: Dockerfile-Rails
  build: .
  command: bundle exec Rails s -p 3000 -b '0.0.0.0'
  ports:
    - "80:3000"
  links:
    - redis
    - db
  environment:
    - REDISTOGO_URL=redis://user@redis:6379/

redis:
  image: redis

db:
  dockerfile: Dockerfile-db
  build: .
  env_file: .env_db

Dockerfile-Rails

FROM Rails:onbuild

ENV Rails_ENV=production

すべてのDockerfileを投稿する必要はないと思う

UPD:自分で修正しました。すべてのコンテナを削除し、docker-compose up もう一度

38
handkock

Onbuildイメージを使用しているため、作業ディレクトリはコンテナイメージにマウントされます。これは開発に非常に適しています。コードを編集するとアプリがリアルタイムで更新され、たとえば移行を実行するとホストシステムが更新されるためです。

これは、サーバーが実行されるたびにホストシステムのtmpディレクトリにpidファイルが書き込まれ、サーバーが正しくシャットダウンされない場合はそこに残ることも意味します。

ホストシステムから次のコマンドを実行します。

Sudo rm tmp/pids/server.pid 

Ctrl + cを押してもpidファイルは削除されないため、例えばdocker-composeでフォアマンを使用している場合、これは非常に苦痛です。

48
TopperH

実際に何が起こっているのかを理解するまで、私は同じ問題に少し困惑していました。本当の答えはさらに下にあります...最初は、docker-compose.ymlファイルで次のコマンドのようなものを試してください。

command: /bin/sh -c "rm -f /Rails/tmp/pids/server.pid && Rails server puma"

(私はAlpineとbusyboxを使って物事を小さくしているので、bashはありません!-cはbashでも動作します)これにより、ファイルが存在する場合は削除され、コンテナが保持する問題に悩まされなくなります終了してそこに座ってコマンドを実行できません。

残念ながら、サーバーの前に/ bin/shの追加レイヤーを追加し、サーバーが停止コマンドを取得できないようにするため、これは適切なソリューションではありません。その結果、docker stopコマンドは正常に終了せず、常に問題が発生します。

Docker-compose upを使用してrmコマンドを実行し、ファイルを削除してから、コマンドをサーバーに戻して続行します。

ただし、本当の答えは、単純なdocker-entry.shファイルを作成し、exec形式 Entrypoint Documentation を使用して呼び出して、シグナル(停止など)がサーバープロセスに到達するようにすることです。

#!/bin/sh
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "$@"

注:最後の行でexecを使用して、Railsがpid 1(つまり、追加のシェルなし)として実行され、シグナルが停止することを確認します。そしてDockerfile(またはcompose.yml)ファイルはエントリポイントとコマンドを追加します

# Get stuff running
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["Rails", "server", "puma"]

繰り返しますが、sh -c ""として実行する代わりにexecされるように[]形式を使用する必要があります。

38

私がやったことは、ドッカーのbashシェルに行くことです:

docker-compose run web /bin/bash

その後、次のファイルを削除します

rm tmp/pids/server.pid

それが役立つことを願っています!

5
charlesdg

これは、 Brendon Whateleys ???? answer の適応バージョンです

Docker Composeソリューション

1。 docker-entrypoint.shを作成します

#!/bin/bash
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "$@"

2。 docker-compose.ymlを調整します

services:
  web:
    build: .
    entrypoint: /myapp/docker-entrypoint.sh
    command: ["Rails", "server", "-b", "0.0.0.0"]
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"

アプリをマウントした場所へのパスを提供する必要があることに注意してください:iE:/myapp

2.5許可エラーが発生した場合

これをターミナルで実行してくださいbeforerunning docker-compose upまたはイメージを構築します。ありがとう sajadghawami

chmod +x docker-entrypoint.sh

3。 server.pidを手動で再度削除する必要がないことをお楽しみください

????

5
davegson

私の仕事のために:

docker-compose run web bash

そして、コマンドcd(win 7ツールボックスを使用しています)を使用してフォルダーごとに移動するため、最終的にはbashで使用します。

rm tmp/pids/server.pid

5
mrpepo877

tmp/pids/server.pidが実際に存在しない場合に問題がある場合:

(Dockerバージョン1.11.2、ビルドb9f10c9)

  1. 私のために働いた解決策は、正確なコマンドをdocker-compose.ymlに追加することです、例えば:

    command:
       Rails s -b0
    

    このコマンドを使用すると、実際には単にDockerfileのCMDを複製できます-古い.pidの問題は表示されません。

  2. DockerfileのCMDを使用する必要がある場合、他のオプションは、オプション--buildで実行してイメージを再構築することです。

    docker-compose up --build
    

    時間はかかりますが、最初の解決策の方が便利です

3

Docker-compose.ymlファイルで、アプリケーションコンテナー自体の下で、次のいずれかを使用できます。

コマンド:["rm /your-app-path/tmp/pids/server.pid && bundle exec bin/Rails s -p 3000 -b '0.0.0.0'"]

または

コマンド:["rm /your-app-path/tmp/pids/server.pid; foreman start"]

いずれかの「;」の理由または、「&&」は、rmがファイルの検索に失敗した場合に後者が終了信号を送信し、コンテナを強制的に停止します。前のものは引き続き実行されます。

なぜこれが最初に引き起こされるのか?合理的な理由は、サーバー(puma/thin/whatever)が正常に終了しない場合、ホストマシンにpidを残して終了エラーが発生することです。

0
Jimmy M.G. Lim

冒険好きなら、気軽にコードベースでserver.pidを検索し、pidが書き込まれている場所を確認してください。そうすることで、書き込みを許可しないかどうかを確認して、根本的な問題を解決できます。一見、pidの作成は、2つの異なるdockerコンテナで重複したサービスを実行するのを防ぐのに役立つからです。しかし、それはそのままdockerで処理する必要があります。何らかの理由でそうでない場合は、ポート衝突の方法論が間違いなくそれを処理し、警告する必要があります。注:一般にシステムを動かしているため、このアプローチはまだ試していません:)

または、Makefileにコマンドを含めることもできます。タスクがこれを行う場所:

仕事:
docker-compose stop service_name
docker-compose rm service_name
rm -f ./tmp/pids/server.pid(またはpidファイルの相対パス名)
docker-compose up service_name

そして、vrooom make taskターミナルでEnterキーを押します。上記のタスクコマンドは、実行するサービスがdocker-compose.ymlという名前のファイルにあることを前提としています

名前が異なる場合、コマンド

docker-compose stop service_name-> docker-compose -f your-compose-filename.yml stop service_name

などなど。

=====================これを更新するために戻ってきました。そのため、write_pidメソッドの機能をコメントアウトしてみました。基本的にメソッド定義を保持しますが、何もさせません。今のところうまく機能しています。 pidはまったく書き込まれません。 Dockerでサービスを実行している場合、これは完全に安全だと思います。

0
Sheetal Kaul