dockerコンテナ起動時に実行する.shファイルの権限
はじめに
今回コンテナ起動時にまとめてコマンドを実行するために.sh
ファイルを作ったのですがその際パーミッション関係でcompose-up
時に.sh
が起動できなかったので対処法をメモしておきます。
問題のコード
#!/bin/bash
# ディレクトリが存在しない場合のみ作成
if [ ! -d "/src/server" ]; then
mkdir -p /src/server
fi
# コンテナが終了しないようにするためのコマンド
tail -f /dev/null
ディレクトリがなかったら作成するだけのコードですsrc/script
内にあります。
ホストマシン上では問題なく動作しました。
次にDockerfile
です
FROM ubuntu:latest
# 作業ディレクトリの設定
WORKDIR /src
# ソースコードのコピー
COPY ./src .
# 起動時にエントリーポイントスクリプトを実行
CMD ["/src/script/entrypoint.sh"]
コンテナの起動にはdocker-compose
を使用しています
services:
サービス名:
container_name: ${CONTAINER_HOST}
hostname: ${HOST}
env_file: .env
tty: true
build:
context: .
dockerfile: ./docker/Dockerfile
docker compose build
してdocker compose up -d
すると
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/src/script/entrypoint.sh": permission denied: unknown
make: *** [up] Error 1
実行権限が無いと怒られます。
これはコンテナ内でファイルの権限が有効になっていないのが原因です
修正
chmod
コマンドをコンテナ起動時に動かして権限を上げればOKです
FROM ubuntu:latest
# 作業ディレクトリの設定
WORKDIR /src
# ソースコードのコピー
COPY ./src .
# エントリーポイントスクリプトに実行権限を付与
RUN chmod +x /src/script/entrypoint.sh
# 起動時にエントリーポイントスクリプトを実行
CMD ["/src/script/entrypoint.sh"]
これでコンテナ内部を見てみると
# ls
script server
ちゃんとserver
ディレクトリが作成されています
しかしこの方法には欠点があります...
docker-compose
ファイルを少しいじりましょう
多くの方はコンテナのボリュームをホストマシンにマウントすると思います
services:
サービス名:
container_name: ${CONTAINER_HOST}
hostname: ${HOST}
env_file: .env
tty: true
build:
context: .
dockerfile: ./docker/Dockerfile
volumes:
- ./src:/src
コンテナ内のsrc
をホストのsrc
にマウントしています
これで実行すると...
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/src/script/entrypoint.sh": permission denied: unknown
make: *** [up] Error 1
パーミッションエラーが出ます
次にこの対策をするためにDockerfile
を編集します
FROM ubuntu:latest
# 作業ディレクトリの設定
WORKDIR /src
# ソースコードのコピー
COPY ./src .
# 起動時にエントリーポイントスクリプトを実行
CMD ["bash", "-c", "chmod +x /src/script/entrypoint.sh && /src/script/entrypoint.sh"]
これでdocker compose build
してdocker compose up -d
すると
問題なくコンテナ内にserver
ディレクトリが作成されます
原因
なぜCMD
で権限を与える必要があるかを簡単に説明していきます
コンテナが立ち上がるまでの流れは次のようになっています
まずRUN
で権限を与えた場合です
権限を与えた後に再びホストからファイルがマウントされて権限が無い状態に上書きされています
次にCMD
の場合です
CMD
はマウント後に実行されるので問題なく権限が付与されています
おわりに
ボリュームをマウントした途端権限がつかなくなってしまったので焦りましたが解決することができました
.sh
ファイル以外にも権限が必要なときには使えると思うので参考になったら幸いです
Discussion