🤷‍♂️

dockerコンテナ起動時に実行する.shファイルの権限

2024/09/02に公開

はじめに

今回コンテナ起動時にまとめてコマンドを実行するために.shファイルを作ったのですがその際パーミッション関係でcompose-up時に.shが起動できなかったので対処法をメモしておきます。

問題のコード

entrypoint.sh
#!/bin/bash

# ディレクトリが存在しない場合のみ作成
if [ ! -d "/src/server" ]; then
	mkdir -p /src/server
fi

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

ディレクトリがなかったら作成するだけのコードですsrc/script内にあります。
ホストマシン上では問題なく動作しました。

次にDockerfileです

Dockerfile
FROM ubuntu:latest
# 作業ディレクトリの設定
WORKDIR /src
# ソースコードのコピー
COPY ./src .
# 起動時にエントリーポイントスクリプトを実行
CMD ["/src/script/entrypoint.sh"]

コンテナの起動にはdocker-composeを使用しています

docker-compose.yml
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です

Dockerfile
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ファイルを少しいじりましょう
多くの方はコンテナのボリュームをホストマシンにマウントすると思います

docker-compose.yml
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を編集します

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