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 | => Run
Railsサーバー-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
もう一度
Onbuildイメージを使用しているため、作業ディレクトリはコンテナイメージにマウントされます。これは開発に非常に適しています。コードを編集するとアプリがリアルタイムで更新され、たとえば移行を実行するとホストシステムが更新されるためです。
これは、サーバーが実行されるたびにホストシステムのtmpディレクトリにpidファイルが書き込まれ、サーバーが正しくシャットダウンされない場合はそこに残ることも意味します。
ホストシステムから次のコマンドを実行します。
Sudo rm tmp/pids/server.pid
Ctrl + cを押してもpidファイルは削除されないため、例えばdocker-composeでフォアマンを使用している場合、これは非常に苦痛です。
実際に何が起こっているのかを理解するまで、私は同じ問題に少し困惑していました。本当の答えはさらに下にあります...最初は、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されるように[]形式を使用する必要があります。
私がやったことは、ドッカーのbashシェルに行くことです:
docker-compose run web /bin/bash
その後、次のファイルを削除します
rm tmp/pids/server.pid
それが役立つことを願っています!
これは、 Brendon Whateleys ???? answer の適応バージョンです
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を手動で再度削除する必要がないことをお楽しみください
????
私の仕事のために:
docker-compose run web bash
そして、コマンドcd(win 7ツールボックスを使用しています)を使用してフォルダーごとに移動するため、最終的にはbashで使用します。
rm tmp/pids/server.pid
tmp/pids/server.pid
が実際に存在しない場合に問題がある場合:
(Dockerバージョン1.11.2、ビルドb9f10c9)
私のために働いた解決策は、正確なコマンドをdocker-compose.yml
に追加することです、例えば:
command:
Rails s -b0
このコマンドを使用すると、実際には単にDockerfileのCMDを複製できます-古い.pid
の問題は表示されません。
DockerfileのCMDを使用する必要がある場合、他のオプションは、オプション--build
で実行してイメージを再構築することです。
docker-compose up --build
時間はかかりますが、最初の解決策の方が便利です
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を残して終了エラーが発生することです。
冒険好きなら、気軽にコードベースで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でサービスを実行している場合、これは完全に安全だと思います。