読書メモ「Docker&仮想サーバー完全入門 Webクリエイター&エンジニアの作業がはかどる開発環境構築ガイド」
はじめに
Dockerを勉強しよう(n年ぶりn回目)と思い、購入しました。
この記事は次の書籍を読みながら、個人的に大事そうだなと思った部分のメモ書きです。
記事最後の「まとめ」は書評となっています。
『Docker&仮想サーバー完全入門 Webクリエイター&エンジニアの作業がはかどる開発環境構築ガイド』
リブロワークス (著)
記事の対象読者
- Dockerの基本的な使い方を知りたい方
- 本の内容が気になる方
Chapter1 なぜ開発サーバーが必要なのか
サーバーにLinuxが使われるのはなぜか
- オープンソースかつ無料で使える
- 初期費用を抑えられる
- 安定して稼働できる
- WinやMacのような個人向けOSとは違って落ちにくいような設計がされている。(GUIを取り除くなど)
- 細かいユーザーやファイルの管理
- パーミッションの設定など
豊富なディストリビューションがある。Alpineはシンプルで非常に軽量ゆえにコンテナでよく使われる。
Chapter2 コンテナとは一体何もの?
コンテナの仕組み
- OSにインストールされたDocker上に作成する
- 1つのマシンに複数作成が可能で、アプリケーション用コンテナとDB用コンテナを作成して連携させることも可能
- コンテナと仮想マシンの違い
- 仮想マシンはOSが動作しているが、コンテナはOSを含まない
- コンテナの場合、カーネルはホストOSのものを利用する
- OSを直接マシンにインストールするわけではないので仮想マシンに比べると軽い
コンテナのメリット
- ホストOSを汚さずに環境を構築できる
- 環境構築の手順をコード(Dockerfile)で管理できる
- IaC(Infrastructure as Code)を実現できる
- 異なるOSやマシンでも同じ環境を再現できる
コンテナのデメリット
- 学習コストが必要
- 本番環境で使うとなるとコンテナについて深い知識が必要となる
- Linuxの知識
- コンテナ管理を行うKubernetesなどのオーケストレーションツールの知識
- コンテナはホストOSのカーネルを利用しているので、ホストOSのバージョン差異によって動作しない場合がある
Docker Image を pull するコマンド
docker image pull
コマンド例
docker image pull イメージ名:タグ名
MariDBをpullするコマンド
docker pull mariadb:10.4
コンテナのライフサイクル
コンテナのライフサイクルには下記がある。
- 作成
- Docker Imageからコンテナを作成した状態。まだ動いていない。
- 実行
- コンテナを動作せた状態
- 停止
- 実行していたコンテナを停止させた状態。
- 削除
- コンテナを削除した状態。再度利用するには再生成が必要。
Chapter3 Dockerを使うための環境を構築しよう
Dockerのアーキテクチャ
Dockerは「クライアント/サーバーシステム」。Dockerクライアント、Dockerデーモン、レジストリの3つの要素で構成されている。
- Dokcerクライアント
- DockerコマンドをつけるようにするためのCLIであったりGUI。
- Dockerデーモン
- クライアントからのリクエストを受け付けて、コンテナの作成や実行、イメージのpullを行う。クライアントとの通信にはREST APIが使われている。
- レジストリ
- Docker Hub のこと。Dockerイメージをpullできる。
業務で叩いている docker xxxx
コマンドがクライアントの役目で、そこから後の処理はデーモンがやっているみたいな感じ。
Docker Desktop の使用条件 ~Macの場合
IntelチップとAppleシリコンの両方で使うことが出来る。
ただし、Appleシリコンで利用する場合は Rosetta2 のインストールが推奨されている。
Rosetta2 は Intelチップ用に作られたアプリをAppleシリコンMacで使えるようにするためのソフトウェア。
ただし、イメージによってはARMアーキテクチャ(Appleシリコンに使われているアーキテクチャ)が非対応の(配布されていない)ものがある。
イメージを pull する際は DockerHub の Supported architectures に arm64 が含まれていることを確認すること。
Chapter4 Dockerを使った仮想サーバー構築に挑戦!
この章以降からハンズオン形式。
Apatchコンテナの作成〜削除まで
使用するイメージ
作成用のコマンド
docker container run --name apache01 -p 8080:80 -d httpd
上記を叩いて localhost:8080 にアクセスできたら構築完了
停止用のコマンド
docker container stop apache01
削除用コマンド
docker container rm apache01
なお、Docker Desktopからもコンテナの状態を確認できる。
Docker Compose とは
複数コンテナをラクに作れるソフトウェア。Docker Desktop にデフォルトで同梱されている。
設定ファイルに yaml
を使う。
Dockerを使う必要があるけど細かい勉強をする時間がとれない人間にうってつけ。
docker compose up -d
Docker / Docker Composeについての古い書き方
古い記事だと docker container run
ではなく docker run
を利用している。
イメージを取得するのに docker image pull
ではなく docker pull
を利用している記事がある。
これからDockerを使う場合は container
や image
を付けるのが推奨。
また、Docker Compose も古い書き方が記事検索に引っかかっている状況。
推奨されるのは docker compose
コマンドである。古い書き方は docker-compose
になっている。(ハイフンで繋いでいる)
また、yamlファイルは compose.yaml
が推奨されている
古い記事だと docker-compose.yaml
とかになっている。
Docker Compose ファイルの先頭に version: "3"
みたな記述が書いてある記事があったりするが、これらは非推奨となっている。
ホストOSからコンテナ内へファイルをコピーする
docker compose cp ホストのファイルパス コンテナ名:コンテナ内のファイルパス
コンテナからホストOSへファイルをコピーする
前述と逆に書けばOK
docker compose cp コンテナ名:コンテナ内のファイルパス ホストのファイルパス
使い終わったコンテナの後始末
docker compose down
コンテナが実行中であっても使用可能で、紐づくネットワークも削除してくれる。
類似コマンドで docker compose rm
があるが、こちらは実行中のコンテナには利用できず、紐づくネットワークの削除もしてくれない。
コンテナ内でコマンドを実行する
docker compose exec コンテナ名 実行したいコマンド
コンテナ内でシェルを立ち上げる
docker compose exec コンテナ名 /bin/bash
さまざまな機能を1つのコンテナに詰め込まない
1つのコンテナに機能を盛り込みすぎると再利用性を損なう。メンテナンスのコストも増加する。
1つのコンテナにWordPressとMariaDBを詰め込んだ場合、MariaDBからMySQLに変更したいときに変更が面倒くさい。
これはプログラミング全般に言える気がする。(一つの関数で多くのことをやりすぎないみたいな
データの永続化(ボリューム)
services:
コンテナ名:
image: 使用するイメージ名
volumes:
- 「volumes」に定義したボリューム名:「コンテナ内のパス」
volumes:
ボリューム名:
データの永続化(バインドマウント)
ホストOSのフォルダやファイルをマウントする仕組み。
services:
コンテナ名:
image: 使用するイメージ名
volumes:
- ホストOSのフォルダ:コンテナ内のパス
公式では前述のボリュームの利用が推奨されている。
Dockerfileを作成する時
どんなイメージを作りたいのかを整理してから Dockerfile
に落とし込む必要がある。
どんな手順でインストールするおか、そのコンテナに何をさせるのか〜みたいな。
Flaskコンテナ作るときにハマった
書籍に載っているコードをそのまま使っても動かなかった。
自分のインテルMacでは 5000番ポートがすでに使われていた。
原因はAirPlay Receiverだった。
とりあえず port
を "5001:5000"
に設定したらOKだった。
次に docker compose up -d
を叩いたらすぐにコンテナが落ちる。
ログを確認すると下記のようなエラーが出ていた。
ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (/usr/local/lib/python3.10/site-packages/werkzeug/urls.py)
エラー内容でグったら下記の記事を発見。
Flaskのバージョンの問題っぽかった。
Dockerfile
に記載してある flask
のバージョンを変更し、 Werkzeug
のバージョンも固定した。
FROM python:3.10
WORKDIR /usr/src/app
- RUN pip install flask==2.1.0
+ RUN pip install flask==2.2.2
+ RUN pip install Werkzeug==2.3.7
CMD [ "flask", "run", "--host=0.0.0.0" ]
その後、 docker compose build
をしてイメージの再ビルドを行ってから docker compose up -d
を叩いたら無事に動作が確認できた。[1]
Dockerfileを書き換えたらやること
Dockerfile
を書き換えた後、そのまま docker compose up -d
を叩いても、変更前のイメージが使われる。したがって必ず次の手順を踏むこと。
- Dockerfileを更新する
docker compose build
docker compose up -d
といった感じだ。
またはイメージの再ビルドとコンテナの実行っていう便利コマンドが有るのでそちらを使ってもよい。
docker compose up -d --build
ただし上記コマンドを叩いても DockerFile
の更新が反映されない場合がある、そんな時はキャッシュを使わずにビルドを行う下記コマンドを叩く。
ただし、この場合はキャッシュを利用しないのでビルドに時間がかかることを留意しておく。
docker compose build --no-cache
コンテナのネットワークの話
- コンテナとコンテナの外を繋ぐネットワークと、コンテナ間を繋ぐネットワークが必要。
- 例えばWordPressコンテナがブラウザからアクセスできるのはコンテナとコンテナの外を繋ぐネットワークのおかげ。
- WordPressコンテナがMariaDBコンテナにデータを保存できたのはコンテナ間のネットワークが繋がっているおかげ。
- 外部からコンテナ内部へ通信するにはポートフォワーディングが必要。
- 特定のポート番号あての通信を、あらかじめ設定した別のポート番号へ転送すること。
CHAPTER 5 すぐに使えるDocker設定ファイル集
メモは割愛。
以下のコンテナ作成方法が記載されているので、手を動かしながら必要なコンテナの立ち上げ方が学べる。
- Debian
- Ubuntu
- MariaDB + phpMyAdmin
- PostgreSQL
- PostgreSQL + pgAdmin4
- nginx
- Django
- Ruby
- Ruby on Rails
- PHP + Apache + MariaDB
- Spring Boot
まとめ
業務で誰かが作った DockerFile
や compose.yml
を利用してコンテナを立ち上げたことは数あれど、実際に自分自身でこれらのファイルを作成するための経験がなかった自分には良書だと感じました。
サンプルが豊富にあるので、これらを実際に触ってみて少しづつDockerの設定ファイルを書く経験値を積んでいけば業務に活かせそうだなと思いました。
Flaskの部分は本に載っている事を写経しても自分の環境では動かなかったので、自分で調べて動かすことができたのでかなり勉強になった気はしました。
個人的には Node.js
環境を立ち上げるコンテナの作成方法があれば嬉しかったですが、そこは自分自身でチャレンジします。
-
ひょっとするとflaskのバージョンを変更するだけで良かったかもしれない ↩︎
Discussion