1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dockerを学習してみた

1
Posted at

はじめに

Dockerやコンテナについてふわっと理解できているくらいで、どんなことが便利なのか?実際にはどのように使用するのか?が分かっていなかったので今回学習してみました。
自分なりにわかりやすくまとめたのでこれからDockerを学習する方の参考になればいいなと思っています。

コンテナの特徴

コンテナはコンテナ内のプロセスがすべて終了した際にExitされる。

Dockerfileとは

イメージをカスタマイズするために使う。
dockerhubに存在するイメージは最低限の機能しか入っておらず、カスタマイズが必要。

外に持ち出せるのはイメージのため、コンテナではなくイメージをカスタマイズする。

FROMエリア

元となるdockerイメージを指定できる。

Dockerfile
# FROM {元となるdockerイメージ名}
FROM ubuntu:20.04

RUNエリア

コンテナ起動時にシェルで実行したいコマンドを指定できる。

Dockerfile
FROM ubuntu:20.04

# RUN {任意のコマンド}
RUN apt update
RUN apt install -y curl

COPYエリア

ホストマシンの任意のファイルやディレクトリをコンテナにコピーできる。
イメージビルド時にコピーされるため、ビルド後に元ファイルを操作しても影響はない。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

# COPY {元ファイルのパス} {コンテナ内のパス}
COPY ./hello.txt /app/

CMDエリア

コンテナ実行時のデフォルトコマンドを設定できる。
Dockerfileで1度のみ使える。複数ある場合最後のCMDのみ有効になる。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY ./hello.txt /app/

# CMD ["実行ファイル", "パラメータ1", "パラメータ2"]
CMD ["ls", "-a"]

ENVエリア

環境変数を設定できる。1度に複数個の環境変数を設定することも可能。
イメージ作成時とコンテナ実行時に利用する変数を作成。
コンテナの中で環境変数によって処理を動的に変更するときなどに有効。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY ./hello.txt /app/

# ENV {キー1} = {値1} {キー2} = {値2}
ENV hello="Hello World"
ENV hoge=HOGEHOGE # スペースが入っていなければ""は必要なし

CMD ["bash"]
bash実行結果
root@d2195c998190:/# echo $hello
Hello World

ARGエリア

イメージ作成時に利用する変数を作成。
Dockerfileの中でのみ使いたい変数などを設定する際に有効。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY ./hello.txt /app/

ENV hello="Hello World"
ENV hoge=HOGEHOGE

# ARG {キー1} = {デフォルト値}
ARG message # デフォルト値無しでも問題なし

CMD ["cat", "message.txt"]
コマンド実行結果
docker image build --build-arg message="Hello Message" .
docker container run -it {ビルドされたイメージ名}
Hello Message

WORKDIRエリア

RUNやCMDなどの作業ディレクトリを指定できる。
(未指定の場合、"/"が作業ディレクトリになっている)

Dockerfile
FROM ubuntu:20.04

# WORKDIR {ディレクトリパス}
RUN echo "" > 1.txt
WORKDIR /app/my_dir
RUN echo "" > 2.txt
WORKDIR ..
RUN echo "" > 3.txt

CMD ["bash"]
bash実行結果
root@17e3129684cf:/app# ls
3.txt  my_dir
root@17e3129684cf:/app# cd my_dir
root@17e3129684cf:/app/my_dir# ls
2.txt
root@17e3129684cf:/app/my_dir# cd ../..
root@17e3129684cf:/# ls
1.txt  app  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

ビルドコンテキストとは

ビルドに必要なファイル群をDockerデーモンに送信するディレクトリ(の範囲)のこと。
DockerfileのCOPYやADDで参照できるのはコンテキスト内のファイルのみ。

例コマンド
docker image build -f docker/Dockerfile .

上のコマンドでは-fオプションでDockerfileの場所を、.でビルドに必要なファイルの送信範囲をビルドコンテキストとして伝えている。

.dockerignoreとは

.dockerignoreファイルに記載したものはビルドコンテキストから除外できる。
クレデンシャルな情報や重たいファイルを記載する。

イメージレイヤーとは

イメージの変更差分がレイヤーとして保存される。
Dockerfileで実行したものが1行ずつ保存される感じ。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY ./hello.txt /app/

CMD ["ls", "-a"]

上の例だと5つのレイヤーができる。

イメージレイヤーで意識すること

レイヤーは少ないほうがイメージレイヤーの容量が小さくなる。

Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY ./hello.txt /app/

CMD ["ls", "-a"]

↓

Dockerfile
FROM ubuntu:20.04

# RUNをまとめて1行にした
RUN apt update && apt install -y curl

COPY ./hello.txt /app/

CMD ["ls", "-a"]

多くのソフトウェアをインストールするような状況ではレイヤーを細かく分けた方が良かったりする。

開発初期でインストールするソフトウェアが多かったり、ほかにもインストールが必要になるものがあるときはレイヤーを細かく分け、最終的にひとまとめにして容量を減らすのがいいかも。

マルチステージビルドとは

1つのDockerfileでステージごとの環境を分離し、最終イメージには必要なファイルだけを含められる。

例
FROM gcc:12.2.0 AS compiler
WORKDIR /app
COPY ./hello.c .
RUN gcc hello.c


FROM ubuntu:20.04 
WORKDIR /app
COPY --from=compiler /app/a.out .
CMD ["./a.out"]

上の例だと、C言語のソースコードをコンパイルするためにgccを入れたcompiler環境、コンパイルされたファイルを実行するための環境に分かれている。最終イメージには実行環境のみ含まれる。

マルチステージビルドの利点

  1. dockerイメージには実行環境のみ含まれ、その他環境は含まれないためイメージサイズが削減できる
  2. 開発・本番環境を1つのDockerfileで管理できる

データの永続化

ボリュームとは

Dockerが管理しているデータ領域。コンテナとは分離したもののためコンテナが削除されても消えない。

コマンド例
# ボリューム作成
docker volume create my-volume

# ボリュームを紐づけてコンテナ起動
docker container run -v my-volume:/app ubuntu

各コンテナからアクセスすることでデータの読み書きが可能。
例として、my-volumeを/appにマウントしたcontainer-1とcontainer-2がある場合

container-1のbash
# /appにファイル作成
root@d7145dbaeccc:/app# echo "Hello World" > hello.txt
container-2のbash
# /appにcontainer-1で作成されたhello.txtが存在する
root@d7145dbaeccc:/app# ls
hello.txt

バインドマウントとは

ホストマシンの任意のディレクトリとコンテナ内の任意のディレクトリを同期させる。
指定には任意のディレクトリの絶対パスが必要。

動作はボリュームと同じ

ボリュームとバインドマウントの使い分け

ホスト側の状況に依存しないよう、基本的にはボリュームの使用が推奨されている。
ホストの環境に依存したり、ホストからのデータアクセスが必要な場合はバインドマウントが有効。

コンテナのポート制御

コンテナはPORTをホストと接続しないとアクセスできない。
ホストが外部に公開しているポート番号とコンテナのポート番号を紐づけてあげることで初めて外部から接続することが可能になる。

Dockerネットワークとは

通信が必要なコンテナのみのネットワークを作り、その中での通信を簡単にしたり、ネットワーク間の通信を防いだりできる。

ブリッジネットワークとは

複数のコンテナ間の通信を橋渡しする。
ブリッジネットワークでつながれているコンテナ以外は通信できない。

ブリッジネットワークを何も指定せずコンテナを作成した場合、「bridge」というブリッジネットワークに接続される。

コンテナ間を通信させる

ブリッジネットワーク「my-net」を作成して2つのコンテナを接続する。

コマンドプロンプト
# ブリッジネットワーク作成
docker network create my-net

# コンテナ1作成
docker container run -itd --name my-nginx --network my-net nginx

#コンテナ2作成(Dockerfileから作成)
# FROM ubuntu:22.04 RUN apt update && apt install -y iputils-ping curl
docker image build -t my-ubuntu .
docker container run -itd --name my-ubuntu --network my-net my-ubuntu

コンテナのIPアドレスを確認する。

コマンドプロンプト
docker network inspect my-net

-- 略 --
        "Containers": {
            "873a55b9c6ffe5f01baf33de49fd34c801f6a665f17b241536e80dae5b91e933": {
                "Name": "my-nginx",
                "EndpointID": "f50531376f8b972d7dc94fcbbf0bffc2d87c2832077602bd138392c931f42060",
                "MacAddress": "ba:2b:7f:fb:bd:2b",
                "IPv4Address": "172.18.0.2/16", ←IPアドレス
                "IPv6Address": ""
            },
            "dcea08b8c833efb85973d3fd8adeb2d88e08edb3e1955d54df4d1e540bd55c70": {
                "Name": "my-ubuntu",
                "EndpointID": "d293248b3e9d3bea97b2a858c1c09330fb14a5dd9e2ea5e385b0799085105fb4",
                "MacAddress": "1a:00:b6:4c:05:1c",
                "IPv4Address": "172.18.0.3/16", ←IPアドレス
                "IPv6Address": ""
            }
        },
-- 略 --

curlコマンドでHTTPリクエストを送る。

コマンド
docker container exec -it my-ubuntu bash

# my-ubuntuのbash
root@bf05057366a3:/# curl http://172.18.0.2
実行結果
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
-- 略 --

ウェブページのリソースが返ってきたため通信ができた。

ブリッジネットワーク内の名前解決

自身で作成したブリッジネットワークでは、コンテナ名を指定するだけでコンテナ間の通信ができる。

コマンド
docker container exec -it my-ubuntu bash

# my-ubuntuのbash
root@bf05057366a3:/# curl http://my-nginx
実行結果
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
-- 略 --

Docker Composeとは

コンテナの作成やブリッジネットワーク、ボリュームの作成のために実行するdockerコマンドを1つのコマンド実行で環境が作成できるようになる機能。

docker-compose.ymlファイルに環境を作成するためのコマンドを記載し、docker compose upコマンドで実行できる。

docker-compose.yml
version: '3.9'
services:
  api:
    build: ./api
    ports:
      - 8080:8080
コマンド
docker compose up

上記のように実行すると、apiディレクトリに存在するDockerfileがビルドされ、ポート8080に紐づけられた状態のコンテナが作成される。専用のブリッジネットワークも作成される。

コマンド
# 以下を実行した結果と同一
docker image build -t api-img ./api

docker container run --name api -p 8080:8080 api-img

単語メモ

デフォルトコマンド

コンテナ起動時に何も指定されていない場合に1度だけ実行されるコマンド。

-itオプション

-iでコンテナの標準入力をホストOSに接続したまま保持する。
標準入力:ターミナルからコンテナに対して文字を入力するためのパイプラインのようなもの。

-tでコンテナに疑似ターミナル(TTY)を割り当てる。
TTY:改行コードの変換やコンテナからの出力をターミナル上に表示してくれる。

bash

シェルの一種。
シェル:OS(カーネル)に対して指示する際に自然言語を機械語に直してくれる機能。
macのターミナルやwindowsのコマンドプロンプトはシェルを実行するアプリケーション。

ターミナルでコマンド実行 → シェルが機械語に翻訳 → OS(カーネル)が処理を実行

デタッチドモード / フォアグランドモード

デタッチドモード
バックグラウンドでコンテナを動かせるモード。
-dオプションで実行できる。

常駐する必要があったり、コンテナを起動したうえで別のコマンドを実行したいときなどに便利。

フォアグランドモード
何も指定しなかったらこのモードになる。
デバッグや一時的なスクリプト実行などで便利。

ポート

接続先のアプリケーションを一意に特定するためのもの。
クライアントからアプリケーションに接続するためには、IPアドレスでサーバーを特定し、ポート番号でアプリケーションを特定する必要がある。

新旧Dockerコマンド

旧コマンド 新コマンド 用途
docker pull docker image pull イメージをダウンロード
docker images docker image ls ローカルに存在するイメージ一覧を表示
docker rmi docker image rm ローカルに存在するイメージを削除
docker run docker container run イメージからコンテナを作成し起動
docker ps docker container ls ローカルに存在するコンテナ一覧を表示
docker rm docker container rm 停止したコンテナを削除

旧コマンドは短いが、新コマンドの方が何に対しての操作かわかりやすい。
また、今後のメンテナンスは新コマンドに対して行われる想定のため、新コマンドに慣れていくのがいい。

コマンド一覧

コマンド 用途
docker image pull {イメージ名} イメージをダウンロード
docker image ls ローカルに存在するイメージ一覧を表示
docker image rm {イメージ名} ローカルに存在するイメージを削除
docker image inspect {イメージ名} イメージの詳細情報を表示
docker image build {ディレクトリパス} Dockerfileからイメージを作成
docker image history {イメージ名} イメージレイヤーを表示
docker container run {イメージ名} イメージからコンテナを作成し起動
docker container run {イメージ名} {実行したいコマンド名} コンテナを起動して任意のコマンドを実行
docker container exec {コンテナ名} {実行したいコマンド名} Up状態のコンテナに任意のコマンドを実行
docker container ls コンテナ一覧を表示
-aオプション:起動していないコンテナも表示
docker container stop {コンテナ名} コンテナを停止
docker container restart {コンテナ名} コンテナを再起動
docker container logs {コンテナ名} コンテナのログを表示
docker container rm {コンテナ名} 停止したコンテナを削除
docker container prune Up状態以外のコンテナを一括削除
docker container attach {コンテナ名} デタッチドモードのコンテナに接続
docker volume create {ボリューム名} ボリューム領域を新規作成
docker volume ls ボリューム領域一覧を表示
docker volume inspect {ボリューム名} 指定したボリューム領域の詳細情報を表示
docker volume rm {ボリューム名} 指定したボリューム領域を削除
docker network ls ネットワークの一覧を表示
docker network inspect {ネットワーク名} ネットワークの詳細情報を表示
docker network create {ネットワーク名} ネットワークを新規作成
docker network rm {ネットワーク名} 指定したネットワークを削除
docker compose up docker-compose.ymlファイルを実行
docker compose down docker compose upで起動したネットワークとコンテナを停止

オプション一覧

オプション 使用例 用途
-it docker container run -it {イメージ名} 標準入力をOpenにし、疑似TTYを割り当てる
-t docker image build -t {イメージ名:タグ名} {ディレクトリパス} イメージに任意の名前・タグ名を付ける
--name docker container run --name {イメージ名} {任意の名前} コンテナに任意の名前を付ける
--rm docker container run --rm {イメージ名} {実行したいコマンド} コマンド実行後削除
--build-arg docker image build --build-arg {ARGで宣言した変数名}={値} ビルド時に変数の値を設定
--network docker container run --network {ネットワーク名} {イメージ名} 任意のネットワークを紐づける
--target docker image build --target {ステージ名} 任意のステージでイメージ作成
--build docker compose up --build イメージを再作成
-f docker container rm -f {コンテナ名} コマンドを強制実行
-f docker image build -f {ディレクトリパス} Dockerfileを指定
-d docker container run -it -d {イメージ名} デタッチドモードでコンテナ起動
-y apt install -y {パッケージ名} 質問に対して自動でYesを選択
-v docker container run -v {Vol名 or ホスト絶対パス}:{コンテナ内絶対パス} {イメージ名} ボリューム or ホストマシンの任意のディレクトリに接続
-p docker container run -p {ホスト側のポート}:{コンテナ側のポート} {イメージ名} ホスト側のポートをコンテナのポートに紐づける
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?