🐥

Dockerハンズオン

2023/12/01に公開

私が、Dockerハンズオンを行った資料を再編したものです。
また、この記事は 一関高専 Advent Calendar 2023アドベントカレンダーの1日目です。

概要

Dockerとは

コンテナを便利に使うためのツール
Docker logo

コンテナとは、

コンテナの画像

Bing image Creater

これは違う

新しい仮想化技術

概念図

仮想化概念図

従来の仮想化技術

ホストOSの上に仮想化ソフトウェアを用いて、ゲストOSをエミュレートしていた。

OSのイメージを用いて、ゲストOSをインストールする必要があった。

例:

  • QEMU
  • Hyper-V
  • VirtualBox
  • VMware

コンテナの仮想化技術

ホストOSのカーネルを共有して、ホストOSの上でコンテナを動かす。

カーネルとは

OSの中核となる部分のこと。ハードウェアを直接制御する部分。
カーネルが、ハードウェアを直接制御することで、アプリケーションがハードウェアを直接制御する必要がなくなり、ハードウェアに関係なくアプリケーションを動かすことができるようになる。

Open Container Initiative(OCI)でコンテナのフォーマットやランタイムの実装が決められている。

イメージを使用して、コンテナを作成することができる。

設計図と製品の関係に似ている
設計図 → イメージ
製品 → コンテナ

コンテナとイメージの例え

オブジェクト思考のクラスとインスタンスの関係に似ている

クラス → イメージ
インスタンス → コンテナ

より詳細な解説

Linuxは、すべてのプロセスに対して、プロセスIDを割り当てている。プロセスIDは、プロセスを一意に識別しさまざまな制御を行っている。

このプロセスIDに加えてどのnamespaceに属しているかという情報を付与し、プロセスをコンテナごとの分離している。

こうすることで、コンテナでの仮想化を実現している。

イメージとは

コンテナの元となるテンプレート。

コンテナを動かすために必要な情報(ファイル、さまざまなコンフィグ)をひとまとめにしたもの。

コンテナのメリット

  • 仮想環境の作成の時に、イメージだけでいい
    • 手間が少ない
      • ISOファイルをわざわざ準備しなくていい
      • イメージはすぐに使える状態のため、簡単に作成ができる
      • 複数台のマシーンに複数のコンテナを一気にデプロイできる
  • 軽い
    • OSまでエミュレートする必要がないため
    • それぞれのカーネルで必要な処理が一つのカーネルで済むため
    • 一つのサーバに今まで以上の仮想マシーンが載っけられる

また、これらのことにより扱いが簡単なため、開発でもDockerが用いられる。
開発環境をイメージごと運用環境へデプロイ

従来:インストールをサーバごとに直接やる必要があった。

Dockerを使うメリット

  • イメージの作成を容易に行える
    • イメージを手作業で作るのはすごいめんどくさい
      • 設定ファイルを作ってビルドするだけ
    • Docker Hub でイメージが共有されている
      • 100,000 を超えるイメージ
      • 公式が出しているイメージも多い
        • 言語がすでに入っているイメージを用いれば開発環境がすぐに作れる
  • コマンド一つで、簡単にデプロイ
    • イメージとコンテナの管理をどちらもやってるから、簡単

ハンズオン

Dockerのインストール

Docker Desktop は企業等では有料な場合があるため注意
  • mac
    brewを用いた方が楽

    brew install --cask docker
    
  • window
    Pro, Enterprise, Education以外は、WSL2を用いる方法で行う

インストールができない場合

Github アカウントを持っていれば、Github Codespaceを用いてDockerを触ってみることができる

  1. https://github.com/aoki-taquan/docker-in-docker を開く
  2. 右上のCode > Codespaces > Create New Codespaceをクリック
  3. ブラウザ版のVSCodeがDockerが入っているマシーンにリンクされて開くため、そこのターミナルを

Hello World

Dockerアプリを起動する

Dockerは、デーモンプロセスとして動くため、windowならタスクトレイ、 Macはメニューバーに表示されているだけの場合もある

docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Pull complete
Digest: sha256:c79d06dfdfd3d3eb04cafd0dc2bacab0992ebc243e083cabe208bac4dd7759e0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

やっていること、
'hello-world'というイメージがローカルにない

Unable to find image 'hello-world:latest' locally

そのためDocker Hubから、'hello-world'というイメージを探してダウンロードする(pull)

latest: Pulling from library/hello-world
719385e32844: Pull complete
Digest: sha256:c79d06dfdfd3d3eb04cafd0dc2bacab0992ebc243e083cabe208bac4dd7759e0
Status: Downloaded newer image for hello-world:latest

イメージをもとにコンテナが立ち上がり、Hello from Docker!と説明書きをprintしてくれている

Hello from Docker!
...

基本的な使い方

イメージの確認

以下のコマンドで、ローカルにあるイメージを確認できる

docker images

先ほどのhello-worldがローカルにあることがわかる

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    9c7a54a9a43c   6 months ago   13.3kB

それぞれの意味

REPOSITORY イメージの名前
TAG イメージのバージョン
IMAGE ID イメージを一意に識別するためのID
CREATED イメージが作成された日時
SIZE イメージのサイズ

IMAGE IDや、REPOSITORYとTAGを組み合わせて、イメージを指定することができる

イメージの取得

docker pull <イメージ名>:<タグ>

タグを省略すると、latestが指定される

Ubuntuを取得してみる

docker pull ubuntu:latest

ubuntuのイメージが取得できることがわかる

$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
ubuntu        latest    e4c58958181a   8 weeks ago    77.8MB
hello-world   latest    9c7a54a9a43c   7 months ago   13.3kB

versionを指定してみる

docker pull ubuntu:3.10
$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
python        3.10      c2fedeb2859f   6 weeks ago    1GB
ubuntu        latest    e4c58958181a   8 weeks ago    77.8MB
hello-world   latest    9c7a54a9a43c   7 months ago   13.3kB

イメージからコンテナを作成する

docker run <イメージ名>:<タグ>

すぐ終わる

docker run ubuntu:latest

以下のコマンドで起動することで、shellを操作できる

docke run -it ubuntu:latest 

bashを起動したいなら、

docker run -it ubuntu:latest bash

解説

オプションの意味
i: 標準入力を割り当てる
t: tty(仮想コンソール)を割り当てる

イメージを指定した直後に、コマンドを指定すると、コンテナが起動した直後にそのコマンドが実行される

docker run -it <イメージ名> <コマンド>

shellから抜ける方法

  1. exit
    コンテナが終了する

  2. Ctrl + P + Q
    コンテナは終了せず、バックグラウンドで実行され続ける

runとexecでShellから抜ける時の挙動の違い
run exec
exit コンテナが終了する バックグラウンドで実行され続ける
Ctrl + P + Q バックグラウンドで実行され続ける バックグラウンドで実行され続ける

コンテナの確認

以下のコマンドで、起動中のコンテナを確認できる

docker ps
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

停止しているコンテナも含めて確認できる

docker ps -a

a オプションをつけると、停止しているコンテナも表示される

 $ docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED        STATUS                     PORTS     NAMES
27bc600a2586   ubuntu        "/bin/bash"   8 hours ago    Exited (255) 8 hours ago             happy_shockley
8b0d689cb3b5   hello-world   "/hello"      27 hours ago   Exited (0) 27 hours ago              brave_brown

コンテナを削除する

前の章で確認した、コンテナを削除する

それぞれのSTATUSを見て、削除していく

docker ps -a

起動状態から停止状態にする

以下のコマンドで、起動中のコンテナを停止する

docker stop <コンテナID>

停止状態のコンテナを削除する

docker rm <コンテナID>

操作の結果、適切にコンテナの状態が変化していることがわかる

docker ps -a

イメージを削除する

削除するイメージを確認する

docker images

削除コマンド

docker rmi <イメージID>

ubuntuを削除する

docker rmi ubuntu

ubuntuのイメージが削除されたことがわかる

docker images

コンテナにストレージをマウントする方法

docker run -it -v <ホスト側のディレクトリ>:<コンテナ側のディレクトリ> <イメージ名>
docker run -it -v .:/root/moutfolder ubuntu

lsをすることで docker run した場所のファイルがマウントされていることがわかる

ls /root/moutfolder

その他

exec

docker exec <コンテナID> <コマンド>

実行中のコンテナに対して、コマンドを実行するコマンド

attach

docker attach <コンテナID>

実行中のコンテナにアタッチするコマンド

コンテナを自作してみよう

Dockerでは、Dockerfileというファイルを書くことで簡単にイメージを作成することができる

Dockerfileの書き方

構文

FROM <ベースとなるイメージ>
RUN <コマンド>

FROMでベースとなるイメージを指定する

RUNでFROMで指定したイメージに対して、コマンドを実行する

他にもファイルや環境変数、ネットワークの設定ができるため、詳しくは公式ドキュメントを参照

ubuntuに、vim、treeを追加でインストールするDockerfile

vim:テキストエディタ
tree:ディレクトリ構造を表示するコマンド

FROM ubuntu:latest

RUN apt-get update 
RUN apt-get install -y vim tree

Dockerfileからイメージを作成する

docker build -t <イメージ名>:<タグ> <Dockerfileのパス>

-t: イメージ名とタグを指定するオプション

<Dockerfileのパス>は、DockerFileがあるディレクトリのパスを指定する

docker build -t my-ubuntu:latest .

イメージが作成されたことがわかる

docker images

イメージからコンテナを作成する

docker run -it my-ubuntu:latest

vimやtreeがインストールされていることがわかる

vim
tree

Docker Compose

複数のコンテナを一括で管理するためのツール

Dockerには、コンテナ毎に1つのプロセスだけ実行というポリシーがある。
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント

しかし、複数のコンテナを一括で管理したい場合がある。

例えば、Webアプリケーションを作成する場合、WebサーバとDBサーバを別々のコンテナで管理したい。

このような場合に、Docker Composeを用いると便利

詳細は省きます。

Docker Compose とは — Docker-docs-ja 1.9.03 ドキュメント

VScode Remote Container

開発環境で、一々Dockerをアタッチするのは面倒
VSCode のRemote SSH のような感覚で使いたい

Dev Containers を用いると、わざわざDockerfileを書かずに、Microsoftが作ってくれているテンプレートをもとにDocker開発環境を作成することができる

使い方

  1. VSCodeの拡張機能から、Dev Containersをインストールする
  2. 左したの >< をクリックし、Reopen in Containerをクリックする
  3. テンプレートが表示されるので、適当なものを選択する
  4. オプションが表示されるが、基本的にはデフォルトで問題ない
  5. しばらく待つと、コンテナが立ち上がる

これだけで、言語ごとの開発環境が立ち上がる

競合等が、起きることがない(最高😆)

行われていること、

そのフォルダに、 .devcontainer > .devcontainer.jsonというファイルが作成される

そこにテンプレートから選んだものの設定が書かれている
この設定をもとに、コンテナが立ち上がる

このファイルごと、gitでソースコードを共有することで、ほぼ同一の開発環境を複数人で共有できる

まとめ

Dockerは、コンテナを簡単に扱うためのツール

Discussion