- 概要
- 前提
- 規約
- Docker network
- Docker Volume
- Dockerfileを扱う
- コンテナの生成と停止
- Docker Compose
- 猿でもできるコンテナデータベース
- devcontainer
概要
Dockerの勉強を始めてから入門的なことはできるけど、仕組みが完全に理解できていない。なんて自分向けにノートを書きました。
同じように困ってる人が一人でもいるのであれば解決してあげたい。
前提
-
大前提としてDockerのOSはLinuxベースであること
- MACやWindowsのようなGUI操作ではない
- ディストリビューションはレイヤーの一部
-
まずはレイヤーの仕組みを知っておこう
-
Dockerイメージを作成するときに
Dockerfile
に記述された手順に沿って、1つのイメージを作成することになる- この時に作成されたイメージは
レイヤ構造
と呼ばれ、1つの手順は1つのレイヤーに該当する -
RUN
やCMD
が増えれば増えるほどレイヤーの数が増える
- この時に作成されたイメージは
規約
-
レイヤーを理解したうえでDockerには規約と推奨が存在することに留意
-
規約
- コンテナはエフェメラルであること
- .dockerignoreを有効活用する
- 不要なパッケージのインストールを避ける
- コンテナ毎に1つのプロセスだけ実行
- レイヤーの数を最小に
- 複数行の引数はアルファベット順、改行すること
コンテナはエフェメラル(短命:ephemeral
)であること
最小のセットアップで生成・停止・破棄が可能であること
.dockerignoreを有効活用する
.gitignoreみたいに特定のファイル指定をすることで、イメージ作成時、Dockerfileの特定のファイルを除外することができる
> ignoreを作成する例
# ここで指定されたファイルを例外として登録されます
.temp
不要なパッケージのインストールを避ける
複雑さ、依存関係、ファイルサイズ、レイヤー数を減らすために、余分なパッケージはインストールを避ける。
例)データベースイメージにテキストエディタ系のファイルは不要
コンテナ毎に1つのプロセスだけ実行
(特殊な場合を除いて)1つのコンテナの中で1つのプロセスだけの実行にする
複数のコンテナに分けることで、再利用や水平スケールが可能となる
レイヤーの数を最小に
Dockerfile
の可読性を下げないために、使用するイメージやレイヤーは最小化しておくこと
複数行の引数はアルファベット順、改行すること
(可能であれば)複数行の引数をアルファベット順、改行すること
# buidpack-depsの記述する際の例
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
Docker network
概要
コンテナは作られた時は独立した存在として確立される(完全分離:isolation
)
ただし、コンテナ毎に1つのプロセスを実行する関係上、追加の機能や実装にはコンテナ間の連携が必要になる
そこでDocker networkを利用して、コンテナ間通信を行う
ネットワークはすべてユーザ定義ネットワークと呼ばれ、作成や変更を任意に行うことができる
- Dockerはインストールされたときに自動的に3つのネットワークを作成する(デフォルトネットワーク:
Default Networks
)- デフォルトネットワークは削除されない
- bridge
- none
- host
bridge
コンテナ起動時にネットワークを指定しなければ自動的にこれに割り当てられる
Linuxのブリッジ機能を使った通信方法で、コンテナ外まで通信する場合はルーティング機能が使われる
コンテナ内での連携通信など基本はこれ
none
ネットワークの接続が必要ないコンテナを作成する場合に使われるドライバ
設定されると固有のインタフェース名が作られる
host
作成すると操作しているホストマシンと同じネットワークにするドライバ
作成した瞬間にDockerホストマシンと同じネットワークインタフェース、IPアドレスを持つようになる!
それ以外にもユーザーが独自に定義できるネットワークが3つ存在する
- overlay
- ipvlan
- macvlan
overlay
複数のDockerコンテナと接続し、ホストとのルーティングを初めからなくすことができる
本来brigeとhostのコンテナを繋ぐためにはホストマシンとのルーティングが必要
ipvlan
接続時IPv4とIPv6の両方のアドレスを指定し、任意の数値にすることができる
主にポートフォワーディングとかに使う?(扱ったことがない)
macvlan
コンテナにMACアドレス(物理固有アドレス)を設定し、コンテナをネットワーク上の物理デバイスとして表示することができる。
物理ネットワークに直接接続されることが想定された古いアプリケーションを扱う場合などに使われる
Docker Volume
概要
コンテナで生成され利用するデータは、コンテナ間でのやり取りは出来ず、一度削除したら消え、ホストからは操作できないものである
しかし、Docker Volumeを扱うことによってコンテナ間利用されるデータをマウント、永続的に保持することができる
コンテナ外のストレージを利用する機能の総称をDocker Volumeと呼ぶ
-
Docker Volumeは共通で以下のような特徴がある
- Docekr CLIコマンドやDocker APIを使って管理することができる
- LinuxとWindows上のコンテナで動作する
- 複数のコンテナ間で安全に共有することができる
- Volumeを新たに生成すると、その内容はコンテナがあらかじめ用意していた内容になる
-
外部ストレージにマウントする手法として3種類存在する
- bind mount
- volume(匿名ボリューム,名前付きボリューム)
- tmpfs mount
bind mount
とvolume
はホストのファイルシステム上に作成されるが、tmpfs mount
はメモリ領域に作成される点に注意!
bind mount
ホスト側のディレクトリをコンテナ内のディレクトリと共有する
ほかのプロセスに干渉される可能性がある
volume
Dockerの管理の元、ストレージ領域を確保する
コンテナ内での変更がホストマシンに影響しないため、基本はこれを使うこと
- 匿名ボリュームと名前付きボリュームが存在する
- 匿名ボリューム
- 作成する際に名前を作らず、任意のハッシュ値を名前として扱う
- コンテナ停止と共に自動的に削除される
- 名前付きボリューム
- 作成する際に名前とタグを設定する。
-
-rm
オプションを使うことでコンテナ停止と共に自動的に削除される
- 匿名ボリューム
tmpfs mount
メモリ上にストレージを確保する。
- 基本的には一時的に避難されるような状況で使われる。
- ホストまたはコンテナーの書き込み可能レイヤーに保持したくない機密ファイルを一時的に保存する場合など
Docker Volumeを利用するには2つのオプションが存在する
-v
--mount
- 利用するときは基本どちらでもおk(公式は
-mount
を推奨している)-
-v
と-mount
は同じ書き方ではない点に注意 - 一部のオプションを利用したい時は
-mount
を利用する必要あり
-
Dockerfileを扱う
コンテナを生成するためにはDockerfile
と呼ばれるファイルを編集する必要がある
既存のイメージなどに追加でレイヤーを入れることでより多機能のコンテナの作成が可能!
まずはDockerfileを作成する!
任意のディレクトリでDockerfile
(拡張子なし)を作成
FROM:ベースイメージを作成
最初にベースとなるイメージを指定し、ここからコマンドを組み立てていく!
FROM centos:centos7
- ここで指定するディストリビューションでそのあとのコマンドが変わってくるため注意!
- ununtu > apt update
- centOS > yum update
RUN: 任意のコマンドを実行する
Linuxコマンドを実行し、レイヤーを追加していく!
vimを追加するには以下のような記述を行う
RUN yum install -y vim
また、Javaをインストールしたい場合は、 公式サイトからJavaのリンク を参照する
RUN yum -y install https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.rpm
WORKDIR: ワークディレクトリを追加する
操作するディレクトリの絶対パス(推奨)を指定する!
以降はそのディレクトリを基準にDockerfileに書いた操作が実行される。
WORKDIR /usr/src
- このコマンドでは存在しないパスを指定した場合は新規で作成される
- ディレクトリを作成するためには使わない
レイヤーの確認
FROM centos:centos7
RUN yum install -y vim https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.rpm
WORKDIR /usr/src
コンテナの生成と停止
imageを作成
docker image build
を入力することイメージを作成できる!
Dockerfileがある場所で
docker image build --tag docker-java:app .
-
tag
> コンテナの名前とタグを設定する
ビルドしたらdocker images
で実際に作られたか確認すること!
runでコンテナを起動
docker container run
でコンテナ生成と起動を同時に行うことができる
docker container run -itd -v ${PWD}/src:/var/src docker-java:app
-
itd
> 一度コンテナを起動したらそのままにする -
v
> バインドマウントでDockerを同期
stopでコンテナを停止
docker container stop
でコンテナを停止させることが可能
docker container stop docker-java:app
pruneでDockerのお掃除
ビルド、イメージの作成を行っているとキャッシュが溜まるので適宜、クリアしておくこと
# 停止しているコンテナ、ネットワーク、ボリュームの削除
docker system prune
# イメージの一括削除
docker image prune
Docker Compose
複数コンテナを同時に起動したいけど、毎回コンテナを起動するときにdocker container run
するのは大変・・・
そこで、Docker Composeを利用することで一回のコマンドで複数コンテナの起動、bridgeネットワークに接続が可能!
Docker Composeとは
手っ取り早く、コンテナの起動を楽にするツールであり、イメージを作るツールではないこと!
既存のDockerfileに+compose.yml(旧docker-compose.yml)
を使うことによって、複数の生成が可能になる
compose.yml の作成
compose.yml(旧docker-compose.yml)を以下のような感じで記入する(一例)
# バージョンの指定(現在はバージョン指定が推奨されていない!)
# version: '3.9'
# 大まかに作ったものを流していく工程
services:
# 1つ目のコンテナ
db:
# Dockerfileの指定
build: docker/postgresql
# 接続ポートの選択
ports:
- 5432:5432
# 環境変数の指定
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
# bind mountの指定
volumes: [ ./data:/var/lib/postgresql/data ]
# 2つ目のコンテナ
java:
# Dockerfileの指定
build: docker/java
# 接続ポートの選択
ports:
- 9080:9080
# 一度起動したら、そのままにする
tty: true
# bind mountの指定
volumes: [ ./src:/usr/src:cached ]
書き込みが完了したらdocker-compose
コマンドでビルドができる
# ビルドする例
docker-compose up -d
networkの秘密
-
Docker composeは同時に立てた時に自動的にbrigeネットワークを繋いでくれる
-
そのため、立てる際にネットワークオプションを省いても接続が可能になる
-
しかし、デフォルトネームで固定されるため、別途ネットワークオプションを使いたいときはdocker-compose.ymlにnetworkオプションを追記すること
猿でもできるコンテナデータベース
compose.ymlでファイルを作成
services:
# データベースイメージ(MySQL)
db:
image: mysql:8.0.21
command: --default-authentication-plugin=mysql_native_password
restart: always
#ログイン情報
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: hoge
MYSQL_USER: hoge
MYSQL_PASSWORD: hoge
#データベース接続ポート
ports:
- 3306:3306
# 管理者ログインイメージ
adminer:
image: adminer:latest
restart: always
ports:
- 8080:8080
docker compose up -d
でコンテナをたてれば完了
下記リンクに接続するだけでデータベース編集画面に直行
http://localhost:8080/
devcontainer
VSCodeの拡張機能でdevcontainerと呼ばれるツールがある
-
機能の役割としては
- Docker composeをコンテナを開いた際に自動的に実行してくれる
- 構成ファイルをdocker-compose.ymlから読み込むことができる
- 拡張機能をコンテナを開く際に選択できる?
-
こいつ単体だとコンテナのシステム掃除(prune)ができないため、裏でWSLを起動して適宜運用するのがいい?