『実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本』をやって詰まったところ
VSCodeのdevcontainerで開発環境を整えることができるようになってから、私もその流れに乗って、個人の開発はdevcontainerでやってきましたが、少し使ってみると自分のDockerへの理解の浅さからか、思ったように開発環境が作れないといった事象が出てきました。
なので、Dockerをちゃんと学んでみたいと思い、色々調べたところ、Zennでほげさんという方が、無料でDockerについての入門書を公開してくださっており、こちらを頭からやってみました。
コマンドの説明だけではなく、仮想化とは?というところから説明しており、タイトルにもある通り「よくわからない」という状態から抜け出すのにはぴったりな本だと感じました。
2022年4月現在では無料なので、Docker周辺の知識について不安な点がある方は、是非一度読むことをオススメします。
しかし、ほげさんとの環境差分からか、ハンズオンの中で詰まったポイントがあったので、書き留めておきます。
今後、この本に取り組まれる方の助けになれば幸いです。
ちなみに、私の開発環境は以下のとおりです。
- OS : Windows10
- Docker version : 20.10.7
- ターミナル : VSCodeのbash
mount path must be absolute.
3部:ボリューム
のあたりで、以下のようなコマンドが出てきます。
$ docker container run \
--name db \
--rm \
--detach \
--platform linux/amd64 \
--env MYSQL_ROOT_PASSWORD=rootpassword \
--env MYSQL_USER=hoge \
--env MYSQL_PASSWORD=password \
--env MYSQL_DATABASE=event \
--mount type=volume,src=docker-practice-db-volume,dst=/var/lib/mysql \
docker-practice:db
これを私の方で打ってみると、以下のようなエラーが出ました。
docker: Error response from daemon: invalid mount config for type "volume": invalid mount path: 'C:/Program Files/Git/var/lib/mysql' mount path must be absolute.
どうやら、ボリュームのマウント先を指定するdst=/var/lib/mysql
のパスが、ホストマシンの相対パスだと思われているようです。
色々調べてみると、こんな記事が出てきました。
これを参照して、パスの指定を//
から始めるように変更
$ docker container run \
--name db \
--rm \
--detach \
--platform linux/amd64 \
--env MYSQL_ROOT_PASSWORD=rootpassword \
--env MYSQL_USER=hoge \
--env MYSQL_PASSWORD=password \
--env MYSQL_DATABASE=event \
--mount type=volume,src=docker-practice-db-volume,dst=//var/lib/mysql \
docker-practice:db
上記のコマンドに変更してみると、コンテナが作成されました。
init.sqlというディレクトリが作成されてしまう。
3章:バインドマウント
にて、DBの初期化クエリをバインドマウントしてコンテナに配置するというコメントがあります。
$ docker container run \
--name db \
--rm \
--detach \
--platform linux/amd64 \
--env MYSQL_ROOT_PASSWORD=rootpassword \
--env MYSQL_USER=hoge \
--env MYSQL_PASSWORD=password \
--env MYSQL_DATABASE=event \
--mount type=volume,src=docker-practice-db-volume,dst=/var/lib/mysql \
--mount type=bind,src=$(pwd)/docker/db/init.sql,dst=/docker-entrypoint-initdb.d/init.sql \
docker-practice:db
これを実行して、コンテナに入ってテーブルを調べてみると、テーブルが作成されておりません。
コンテナ内の/docker-entrypoint-initdb.d
を調べてみると、init.sqlというディレクトリが作成されていました。
これに関しては、実行しているコマンドにも間違いはなかったので、なにかDockerの新仕様なのか??とかなり難しいところまで調べてしまいましたが、実際のところ原因はすごく単純でした。
/work
ディレクトリでコマンドを実行していなかったのです。
コマンド内の$(pwd)
は、コマンドを実行しているディレクトリを指すため、そこから参照した時にinit.sqlが見つからず、Docker側で空のディレクトリが作成されてしまったというわけです。
きちんと/work
ディレクトリから実行した結果、初期化クエリが実行され、テーブルが作られていました。
実行するディレクトリは確認しないとなと思ったのと同時に、こういう環境構築を会社で行って、複数のメンバーに横展開するときには、各自のメンバーのディレクトリ構造などに依存しないような構成にしたいなとも思いました。
DBにログインできない
3部:Docker Compose
にて、今までのコマンドをdocker-compose.ymlで再現する手順を説明してくれています。
最後まで手順を終え、docker compose up
でコンテナを立ち上げて、アプリケーションを見てみると、トップページやメール送信のページは見えるものの、historyページが見えません。
エラーログを見てみると以下のようなメッセージが
PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user 'hoge'@'172.28.0.4' (using password: YES) in /src/history.php:15
どうやらDBに接続できていないようです。
見直してみると、MySQLのログインパスワードにtypoがありました。
db:
container_name: docker-practice-db
build:
dockerfile: docker/db/Dockerfile
context: .
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: hoge
MYSQL_PASSWORD: pasword
MYSQL_DATABASE: event
volumes:
- type: volume
source: docker-practice-db-volume
target: /var/lib/mysql
- type: bind
source: ./docker/db/init.sql
target: /docker-entrypoint-initdb.d/init.sql
これを修正して、docker compose up --build
でイメージのビルドからやり直しました。
db:
container_name: docker-practice-db
build:
dockerfile: docker/db/Dockerfile
context: .
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: hoge
MYSQL_PASSWORD: password
MYSQL_DATABASE: event
volumes:
- type: volume
source: docker-practice-db-volume
target: /var/lib/mysql
- type: bind
source: ./docker/db/init.sql
target: /docker-entrypoint-initdb.d/init.sql
しかし、まだ接続できていないようです。
docker container exec
でコンテナに入り、環境変数を調べても、何もおかしいところはありません。
# echo $MYSQL_ROOT_PASSWORD
rootpassword
# echo $MYSQL_USER
hoge
# echo $MYSQL_PASSWORD
password
# echo $MYSQL_DATABASE
event
どうしたものかと少し悩んだところ、DBのデータはvolumeにマウントされていることを思い出しました。
そこで、volumeを削除してから再ビルド。
$ docker volume ls
DRIVER VOLUME NAME
local work_docker-practice-db-volume
$ docker compose down
[+] Running 4/4
- Container docker-practice-mail Removed 0.9s
- Container docker-practice-db Removed 0.9s
- Container docker-practice-app Removed 0.9s
- Network work_default Removed 0.1s
$ docker volume rm work_docker-practice-db-volume
work_docker-practice-db-volume
$ docker compose up --build
すると、無事にDBに接続できるようになり、historyページも見えるようになりました。
各ページの最後に、そこのページで作成したリソースの削除手順まで記載してくれていますが、それぞれのページで手順をやり直す際は、一度リソースをすべて削除してからやり直すことをオススメします。
まとめ
私が詰まった点は、大きく上記の3つです。
私の凡ミスもありましたが、本の最後にはデバッグノウハウも記載されていますし、きちんと最初から理解していけば、多少のつまずきポイントは自分で解消して進めることができるというのも実感として得られました。
冒頭にも申し上げましたが、まだこの本を見ていない方は、是非一度ご覧になってみてください。
最後になりますが、ここまで分かりやすい本を無料で公開してくださっているほげさん、有難う御座います!
Discussion