LoginSignup
0
1

【Django x Docker】スクリプトでrunserverの後のコマンドに進まない場合の対応方法

Posted at

概要

DjangoとDockerを使ってローカル環境でコンテナを立ち上げ、スクリプトでpython manage.py runserver 0.0.0.0:8000を実行していたら、このコマンドが原因で次のコマンドに進まないことがあることがわかりましたので解説します。

コマンドの順番によって次に進まないことがある

以下はサンプルのシェルスクリプト。
docker-composecommand:セクションで実行させます。

docker-compose.yaml
## 略 ## 
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: ["./sample-script.sh""]
    volumes:
      - ./myprojects:/code 
    ports:
      - "8000:8000"
sample-script.sh
#!/bin/bash

echo "Hi, this is sample command"

# Djangoのサーバーを起動
python manage.py runserver 0.0.0.0:8000

上記のように、後でDjangoのサーバーを起動するコマンドを持ってくれば、echoコマンドはdocker logに出力されます。

しかし、以下のように逆にすると、echoコマンドは出力されません。

#!/bin/bash

# Djangoのサーバーを起動
python manage.py runserver 0.0.0.0:8000

echo "Hi, this is sample command"

これは、シェルスクリプトの実行がpython manage.py runserver 0.0.0.0:8000でブロックされ、このコマンドが終了するまで次のコマンドに進まないためです。python manage.py runserverは、サーバーが終了するまで実行を続けるため、その行以降のコマンドは実行されません。

解決策:バックグラウンド起動&コンテナ永続化

このような場合、&によってDjangoのサーバーをバックグラウンドで起動させ、また、その後にコンテナが終了しないようにしてあげれば、順番通り出力されるようになります。

#!/bin/bash

# Djangoのサーバーをバックグラウンドで起動
python manage.py runserver 0.0.0.0:8000 &

echo "Hi, this is sample command"

# コンテナが終了しないようにする
tail -f /dev/null

tail -f /dev/nullとは?

/dev/nullは、読み込むと即座にEOF(End of File)を返し、書き込みを行っても何も保持せずに破棄されるという、特殊なファイルです。英語圏では“black hole”と呼ばれているとか。まぁその通りですね。

シェルスクリプトやコンテナは、実行されたコマンドが終了すると通常終了します。では終わらせないためにどうすればいいか?というと、tail -f /dev/nullのように永遠に終了しないプロセスを起動させてあげれば、コンテナが終了せずに動き続けることができる、というわけです。

記事「永遠に終了せず何もしないDockerコンテナを立ち上げる方法」に他にも方法が記載あるので気になる方はご参考まで。

その他エラー:シバン記載漏れによるexec format error

パッと使うサンプル用にシェルスクリプトを作った気でいたら、シバン(シェバン)の書き漏れがありました。

echo "Hi, this is sample command"

# Djangoのサーバーを起動
python manage.py runserver 0.0.0.0:8000

#!/bin/bashのようなシバンがない場合、以下のエラーになりました。

standard_init_linux.go:228: exec user process caused: exec format error

#!/bin/bashとは?

#!/bin/bashとは、シェルスクリプトがどのシェルで実行されるべきかを示す特殊なコメント行(宣言)。シバン(shebang、シェバンライン)と呼ばれます。

これがないと、システムはスクリプトをどのシェルで実行すれば良いかわかりません。
スクリプトがデフォルトのシェルで実行されようとしますが、そのシェルがバイナリ形式ではない場合に"exec format error"というエラーが発生しているんですね。

#!/bin/bashをスクリプトの先頭に追加することで、スクリプトがbashで実行されることが明示されるので、エラーは無くなりました。

0
1
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
0
1