Windows + Docker 環境でシェルスクリプトが動かず not found になる時の対応

環境

  • Windows 10 Home
  • Docker v28
  • Docker Desktop v4
  • WSL v2 (Ubuntu)
  • Git v2

xxxxx.sh: not found

docker-compose.yaml でシェルスクリプトファイルを command から実行した時に、
下記のようなエラーが出た。

$ docker compose up
sample-web-node-1  | /usr/local/bin/docker-entrypoint.sh: 11: exec: bin/setup_node.sh: not found
sample-web-node-1 exited with code 127

コンテナ内に入って直接実行してみてもエラーが出た。
ファイルは存在しているのに not found と言われる。

$ docker exec -it sample-web-node-1 /bin/bash

$ ls bin
setup_node.sh

$ bin/setup_node.sh
cannot execute required file not found

docker-compose.yaml

services:
    sample-web-app:
        image: nginx:1
        working_dir: /var/www/html
        depends_on:
            - sample-web-node
        ports:
            - 8080:80
        tty: true
        volumes:
            - $PWD/app:/var/www/html
            - $PWD/nginx/default.conf:/etc/nginx/conf.d/default.conf
    sample-web-node:
        image: node:22.9.0
        tty: true
        working_dir: /var/www/html
        volumes:
            - $PWD/app:/var/www/html
        command: "bin/setup_node.sh"

app/bin/setup_node.sh

#!/bin/bash

npm install
npm run dev

原因

Windows の改行コードが原因らしい。

Windows の改行コードが CRLF (¥r¥n)に対して、
Linux 系は LF (¥n)になるそう。

シェルスクリプトに改行コード CRLF が含まれると、
意図しない動作やエラーの原因になるぽい。

確認

cat にオプション e をつけることによって改行が可視化される。

改行コードが CRLF の場合

改行が ^M$ になっている。

$ docker exec -it sample-web-node-1 /bin/bash
$ cat -e bin/setup_node.sh
#!/bin/bash^M$
^M$
npm install^M$
npm run dev^M$

改行コードが LF の場合

改行は $ のみになっている。

$ docker exec -it sample-web-node-1 /bin/bash
$ cat -e bin/setup_node.sh
#!/bin/bash$
$
npm install$
npm run dev$

対応やることその1: .gitattributes

.git と同じ階層に .gitattributes ファイルを作成する。

.gitattributes

ファイルの改行コードを LF に変換する。

.gitattributes を後から追加して、
既存ファイルに CRLF が含んでいたら、
該当ファイルを削除して戻すと LF になっているらしい。

text=auto eol=lf

対応やることその2: git config --global core.autocrlf input

扱うファイルの改行コードを LF に統一する。

Windows 側でこの設定を行う前に既にリポジトリがある場合、
リポジトリ内のファイルの改行コードは CRLF になっているので、
クローンし直せば LF として扱うことができる。

$ git config --global core.autocrlf input