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