🐳

読書メモ「Docker&仮想サーバー完全入門 Webクリエイター&エンジニアの作業がはかどる開発環境構築ガイド」

2024/03/10に公開

はじめに

Dockerを勉強しよう(n年ぶりn回目)と思い、購入しました。

この記事は次の書籍を読みながら、個人的に大事そうだなと思った部分のメモ書きです。

記事最後の「まとめ」は書評となっています。

Docker&仮想サーバー完全入門 Webクリエイター&エンジニアの作業がはかどる開発環境構築ガイド

『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で使えるようにするためのソフトウェア。

https://support.apple.com/ja-jp/HT211861

https://zenn.dev/suzuki_hoge/books/2021-07-m1-mac-4ede8ceb81e13aef10cf

ただし、イメージによってはARMアーキテクチャ(Appleシリコンに使われているアーキテクチャ)が非対応の(配布されていない)ものがある。

イメージを pull する際は DockerHub の Supported architectures に arm64 が含まれていることを確認すること。

Chapter4 Dockerを使った仮想サーバー構築に挑戦!

この章以降からハンズオン形式。

Apatchコンテナの作成〜削除まで

使用するイメージ

https://hub.docker.com/_/httpd

作成用のコマンド

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を使う場合は containerimage を付けるのが推奨。

また、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に変更したいときに変更が面倒くさい。

これはプログラミング全般に言える気がする。(一つの関数で多くのことをやりすぎないみたいな

データの永続化(ボリューム)

compse.yaml
services:
  コンテナ名:
    image: 使用するイメージ名
    volumes:
      - 「volumes」に定義したボリューム名:「コンテナ内のパス」
volumes:
  ボリューム名:

データの永続化(バインドマウント)

ホストOSのフォルダやファイルをマウントする仕組み。

compse.yaml
services:
  コンテナ名:
    image: 使用するイメージ名
    volumes:
      - ホストOSのフォルダ:コンテナ内のパス

公式では前述のボリュームの利用が推奨されている。

Dockerfileを作成する時

どんなイメージを作りたいのかを整理してから Dockerfile に落とし込む必要がある。

どんな手順でインストールするおか、そのコンテナに何をさせるのか〜みたいな。

Flaskコンテナ作るときにハマった

書籍に載っているコードをそのまま使っても動かなかった。

自分のインテルMacでは 5000番ポートがすでに使われていた。

原因はAirPlay Receiverだった。

とりあえず port"5001:5000" に設定したらOKだった。

https://www.keisuke69.net/entry/2021/10/29/012608

次に docker compose up -d を叩いたらすぐにコンテナが落ちる。

ログを確認すると下記のようなエラーが出ていた。

ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (/usr/local/lib/python3.10/site-packages/werkzeug/urls.py)

エラー内容でグったら下記の記事を発見。

https://shinshin-log.com/flask-werkzeug/

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 を叩いても、変更前のイメージが使われる。したがって必ず次の手順を踏むこと。

  1. Dockerfileを更新する
  2. docker compose build
  3. 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

まとめ

業務で誰かが作った DockerFilecompose.yml を利用してコンテナを立ち上げたことは数あれど、実際に自分自身でこれらのファイルを作成するための経験がなかった自分には良書だと感じました。

サンプルが豊富にあるので、これらを実際に触ってみて少しづつDockerの設定ファイルを書く経験値を積んでいけば業務に活かせそうだなと思いました。

Flaskの部分は本に載っている事を写経しても自分の環境では動かなかったので、自分で調べて動かすことができたのでかなり勉強になった気はしました。

個人的には Node.js 環境を立ち上げるコンテナの作成方法があれば嬉しかったですが、そこは自分自身でチャレンジします。

脚注
  1. ひょっとするとflaskのバージョンを変更するだけで良かったかもしれない ↩︎

株式会社HAMWORKS

Discussion