目的
自分用のメモです。Dockerを勉強したときに参考のした情報の整理と、学んだ内容のちょっとしたメモです。学んだことを試すためにDevHubというOSSのツールをDockerで動かしてみたのでそれについても触れています。
環境
プライベートで使っているMac。macOS Catalina(10.15)。今流行のM1チップではありません。
インストール
Docker Desktop on Macをインストールした。現在はお仕事で使うと条件によっては有料になるようなので利用条件はきちんとご確認を。趣味で使う分には問題ないようです。
Install Docker Desktop on Mac | Docker Documentation
とりあえず基礎知識を身につける
最初に「Software Design 2021年12月号」の特集を読み始めたのだが、全く何も知らない状態で読むには難しい内容だった。 なので少しだけ読んで諦めて、Docker公式のGet Startedがあるのでそれに従って学ぶことにした。
上記のページにもTutorialが書いてあるが、手順に従って最初に動かすDockerコンテナ自身にも同じTutorialが記載されているのでどちらを見てもよい。
その後、たまたま見つけたこちらの記事を一通り読み、動かしてみる。第1回から第6回まである。
ここまでで、おおなんとなく触れそうだなというところまでは来た。
個人的になるほどと思った点をまとめておく。
- imageを作って、imageからcontainerを作る。
- imageはベースとなるimage指定し、あとは自分の好きな差分を足せばお好みのimageを作り出せる。ベースとなるimageが世の中にいっぱい公開されているので、Node.js環境とかMongo DB環境とかすぐに手に入る。
- imageを作るための設計書がDockerfile。Dockerfileを作って
docker build
コマンドでimageを作る。 docker run
コマンドでimageからcontainerを作り出す。これでプロセスが起動した状態になる。- imageの作り方次第では複数のプロセスを1つのcontainerに入れることができそうだけど、Dockerの思想的には1つのcontainerには1つのプロセスとなるようにするのが基本らしい。
- 複数のプロセスが連動して動くようなアプリケーションの場合それぞれを
docker run
しても良いが、Docker Composeを使うとまとめてdocker run
できる。 - Docker Composeに使うファイルがdocker-compose.yml。作ったら起動や停止には
docker-compose
コマンドを使う。 - containerは孤立した空間で動いているので、container同士はそのままでは通信できない。Docker独自のnetworkを定義してそれを通じて通信できるようにする必要があるが、Docker Composeを使うと割とそれが自然にできるところも便利。またその場合、docker-compose.ymlの
services
配下に書いたサービス名がcontainer同士で通信するときにホスト名として使用できる(localhostって書いてもダメなので注意)。
もう少し実践的なことをやってみる(DevHubを動かす)
私、DevHubというツールのヘビーユーザーなので、DevHubをDockerで動かすことを目標にやってみます。DevHubはNode.jsとMongo DBで出来ているアプリケーションです。
Dockerfileを作ってみる。このファイルはDevHubをCloneしたフォルダの直下に置く。
FROM node:12 WORKDIR /usr/src/app COPY package*.json ./ RUN npm install COPY . . RUN npm run build EXPOSE 3000 CMD [ "node", "app.js", "-p", "3000", "-d", "devhub_db", "-t", "title" ]
通常DevHub環境構築するときはcloneした後に npm install
だけで終わるが、docker build したときにはどうも package.json に書いてある postinstall が実行されていないように見えたので、postinstallに該当する npm run build
を加えたらうまく行った。本当にpostinstallが実行されていなかったのかはきちんと検証できていないが、static/javascripts/devhub_bundle.js などが生成されていなかったのでそう判断した。
なぜ検証できていないのかというと、docker build実行中の標準出力にログとして表示されないから、より正確に言うとnpm installとかしたときのログは一時的に標準出力に表示されるが、完了するとパッと消えてしまうから。消えないようにする方法か、あるいは後からログを確認する方法があれば良いのだが、調べてみても結局わからなかった。残念(誰かわかる人がいたら教えて欲しい)。
さらに .dockerignore ファイルを作成する。これもDevHubをCloneしたフォルダの直下に置く。
node_modules npm-debug.log
作ったDockerfileを使ってdocker buildする。ちなみに -t で指定するタグ名?は、小文字でないとダメらしい。
% docker build -t devhub .
無事にbuildできることを確認できたら、docker-compose.yml を作ってDevHubとMongo DB(とついでにMongo DBの管理ツールのMongo Express)が同時にcontainerとして動くようにする。このファイルもDevHubをCloneしたフォルダの直下に置く。
# Use root/example as user/password credentials version: '3.1' services: mongo: image: mongo:4 restart: always environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example # only if you'd like to persist the DB volumes: - ./db:/data/db - ./configdb:/data/configdb mongo-express: image: mongo-express restart: always environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: example ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ ports: - 8081:8081 devhub: image: devhub working_dir: /usr/src/app environment: MONGODB_URI: mongodb://root:example@mongo:27017/devhub_db?authSource=admin ports: - 3000:3000
ここで起動する mongo
は このdocker-composeで生成するcontainerからのアクセスのみ想定しているので ports
は指定しなかった。もしcontainer外からもアクセスしたいのであれば 27017:27017
を指定すればよい。
mongoは起動時に何も指定しなければ特に認証なしでアクセス可能な状態で起動する。もしcontainer実行時にもそうしたければ、 mongo
の environment
で指定している MONGO_INITDB_ROOT_USERNAME
と MONGO_INITDB_ROOT_PASSWORD
はいらない。その場合の MONGODB_URI
は mongodb://mongo:27017/devhub
とシンプルになる。
mongo
の volumes
はデータベースを永続化したい(containerを停止/削除してまた開始したときにもデータベースの内容を引き継ぎたい)ときに指定する。 volumes
で指定しているディレクトリは事前にディレクトリを作っておく必要はなく、勝手に作成される。
docker-compose.yml の準備が整ったら、docker-composeコマンドで起動する。
% docker-compose up -d
もろもろうまくいっていれば、 http://localhost:3000/ にブラウザでアクセスすればDevHubが動いていることが確認できる。
docker-compose up
で起動したものは、 docker-compose down
で停止する。停止と同時にcontainerの削除も行われる。
% docker-compose down
ここまで一区切り。ここまでのやり方だとdocker build時にテストを実行できていない(と思う)ので、それについてはまた別の記事で。