@peccul is peccu

(love peccu '(emacs lisp cat outdoor bicycle mac linux coffee))

gitとdockerをWindowsで使う時に気をつけること。特に改行コード

環境の差異をDockerで解決できる。と喜んだのもつかの間。 macLinux前提で進めているとやっぱりハマった。

TL;DR

  • Windows 10でもHomeエディションだとHyper-Vが利用できない
    • VirtualBox利用のDocker Toolboxとなり、volumeの記述がそのまま使えない
    • 環境変数を見て上書きするymlを追加した
  • gitの設定で、改行コードがCRLFになる

内容

Windows 10でもHomeエディションだとHyper-Vが利用できない

VirtualBoxの場合、手動で共有フォルダの設定を記述してあげる必要がある しかもその場合は共有フォルダの名前(設定)を起点にvolumeのパスを指定する必要がある

頑張ればvboxmanageを使って、共有フォルダの場所や名前もプロジェクトで固定/自動設定できるが 気軽に試せるwindows環境がないのと面倒なのとで試せていない。

  • 追加の docker-compose.ymlの作成 (docker-compose.toolbox.yml 等の別名で作成)
    • 既存のvolumesの指定を- ./config:/etc/app/configとして
version: '3.7'
services:
  web:
    ...
    volumes:
      - ...
      - ./config:/etc/app/config
    ...
  • VirtualBox側で./dという名前の設定にして共有フォルダに指定しているとする
  • 追加のymlはこんな感じになる(元のvolumesを上書きする記述だけ。//と重ねるのが正しい)
version: '3.7'
services:
  web:
    volumes:
      - //d/config:/etc/app/config
  • そのdocker-compose.ymlを追加するシェルスクリプトを用意 (.toolbox.sh 等)
    • COMPOSE_FILEという環境変数でdocker-composeが読むymlファイルを指定できる
      • docker-compose -f docker-compose.yml -f docker-compose.toolbox.yml ... とコマンドの引数にも指定可能
    • windowsの場合はファイルの区切り文字は ;で、maclinuxの場合は :
if [ "${DOCKER_TOOLBOX_INSTALL_PATH}" ]
then
    export COMPOSE_FILE="docker-compose.yml;docker-compose.toolbox.yml"
fi
[ -x .toolbox.sh ] && . .toolbox.sh

gitの設定で、改行コードがCRLFになる

core.autocrlf=autoの状態でcloneすると、LFのみのファイルをよしなにCRLFのファイルに変更してくれ、 かつ差分がないと扱われる。 手順書にgit configの設定方法を書くのはナンセンスだと考えている。 やるなら curl -L ~~~ | sh くらいして環境構築を自動化しないといけないと思う。

私がハマったのは、何段階かあった。

  • ローカルのファイルがCRLFなので、コンテナ内で実行すると以下のようなエラーが出る
    • これはシェバン行の末尾にCRが付いているので、 /bin/shCRという実行ファイルを探して見つからない状況だと理解している

      sh: /path-to/some.sh: not found

    • 実行する場所でCRを消した
      • for文のところ。元々は/path-to/some.shのみだった
for i in $(grep -lr '\r' *.sh)
do
  sed 's/\r//g' -i $i
done
/path-to/some.sh
  • pre-pushフックスクリプトでローカルのリポジトリをcloneしていて、また改行コードが変わった
    • pre-pushスクリプトではcleanな状態でlinterなどを走らせたかったので、git cloneしていた
    • つまりリポジトリの設定でcore.autocrlfの設定を変更しても効果なし
    • ユーザーの設定(git config --global core.autocrlf)変更が必要だった
    • これはcloneコマンドで明示することにした
git clone --config core.autocrlf=false file://$(pwd) $tmpdir

その他メモ

Editorconfigの設定

.editorconfigで改行コードや文字コードを指定するときは、全てのファイルを対象にしましょう

[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

(なぜか py, jsだけに限定していてcss, xmlが漏れていた)

pre-pushでCR検知

このようなdocker-compose.ymlを./hooksなどにおいておけば

version: '3.7'
services:
  newline:
    image: alpine/git:latest
    working_dir: /code
    volumes:
      - ..:/code
    entrypoint:
      - sh
      - -c
      - "(if git grep -Ilr $$'\r' ; then echo; echo -e \"\\033[31mCR charactor has detected in above file(s). please change newline encoding to LF only\\033[39m\"; exit 1; fi)"

(yaml$エスケープは $$だそうです。これも過去にはまった。\033[は別の投稿で書いた文字色を変更するもの)

以下のようなスクリプト(./hooks/newline.shなど)で コミットされているファイルについてCRが含まれるファイル(バイナリを除く)のパスが列挙されます。 見つかった場合は終了コードが1になるので、エラー扱いでpre-pushフックで使うとpushを防げます。

#!/bin/bash
SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}"); pwd)
cd $SCRIPT_DIR
docker-compose run --rm newline

使用例

$ ./hooks/newline.sh
tmp/crlf.txt

CR charactor has detected in above file(s). please change newline encoding to LF only

参考

stackoverflow.com

docs.docker.com