Edit

はじめに

この記事の対象

・Docker触ったことがない

・Dockerを学ぼうとしても、実行するアプリケーションに関する予備知識が必要な場合が多くて挫折してしまった

この記事の読み方

1から21の数字が割り振られている「実践」に書かれている項目を番号順に実行することで、手を動かして学ぶことができる

コマンド/コード一覧

イメージ

コマンド 操作
docker search <image> イメージの検索
docker image pull <image>:<tag> イメージの取得
docker image ls イメージの一覧を表示
docker image rm <image>:<tag> イメージの削除

コンテナ

コマンド 操作
docker container run <image> コンテナの起動
docker container ls コンテナの一覧を表示
docker container rm <name or container ID> コンテナの削除
docker container run -it –name <name> -h <host name> <image> <command> コンテナ起動+ログイン
exit ログイン中のコンテナから離脱(コンテナが停止する)
Ctrl + p + Ctrl + q ログイン中のコンテナから離脱(コンテナが停止しない)
docker container logs <name> コンテナの作業ログ表示
docker container commit <name> <image>:<tag> イメージをコンテナから作成
docker container rm <name or container ID> コンテナの消去
docker container start <name> 停止中コンテナの起動
docker container attach <name> 起動中のコンテナにログイン(exitを実行するとコンテナが停止する)
docker exec -it <name> /bin/bash 起動中のコンテナにログイン(exitを実行してもコンテナが停止しない)
docker container exec -it <name> <command> 起動中のコンテナでコマンド実行
docker container inspect <name> コンテナの情報を表示
docker container stats <name> コンテナのリソース確認
docker container cp <path_in_host_os> <name>:<directory_in_container> ホストOSからコンテナへのファイルやディレクトリのコピー
docker container cp <name>:<path_in_container> <directory_in_host_os> コンテナからホストOSへのファイルやディレクトリのコピー

Dockerfile

コード 操作
FROM <image>:<tag> ベースイメージを指定
LABEL <key>=<value> Dockerのイメージにメタデータを追加
ENV <key> <value> 環境変数を設定
RUN <command> イメージのビルド中にコマンドを実行
COPY <path> <directory> ファイルとディレクトリをコンテナにコピー
ADD <path> <directory> ファイルとディレクトリをコンテナにコピー
WORKDIR <directory> 作業ディレクトリを指定
ENTRYPOINT [<command>, <arg1>, <arg2>, …] イメージからコンテナを作成したときにコマンドを実行
CMD [<command>, <arg1>, <arg2>, …] 完成したイメージからコンテナを作成するときにコマンドを実行
ARG ビルド時にDockerに渡す変数を定義
EXPOSE ポートを公開
VOLUME マウントポイントを作成して、ホストや他のコンテナからボリュームのマウントを行う

目次

  • Dockerの説明
    • コンテナ
    • イメージ
    • Dockerfile
    • それぞれの関係
  • VMとDockerコンテナの違い
    • VM
    • コンテナ
  • コンテナとVMの使い分け
    • コンテナ向け
    • VM向け
  • 基本コマンド/コード
    • イメージ
      • イメージの検索
      • イメージの取得
      • イメージの一覧を表示
      • イメージの削除
    • コンテナ
      • コンテナの起動
      • コンテナの一覧を表示
      • コンテナの削除
      • コンテナ起動+ログイン
      • ログイン中のコンテナから離脱
      • コンテナの作業ログ表示
      • イメージをコンテナから作成
      • コンテナの消去
      • 停止中コンテナの起動
      • 起動中のコンテナにログイン
      • 起動中のコンテナでコマンド実行
      • コンテナの情報を表示
      • コンテナのリソース確認
      • ホストOSとコンテナ間のファイルやディレクトリのコピー
    • Dockerfile
      • 基本コード
      • イメージのビルド
      • マルチステージビルド

Dockerの説明

「コンテナ」を利用した基盤ソフトウェア

コンテナ

container.png

アプリケーションを動作させるのに必要なライブラリやアプリケーションを使えるようにしたホストOS上にある論理的な区画のこと

  • あたかも個別のサーバーのように使える
  • プロセス、ネットワーク、ファイルシステムが区画化されている
  • Dockerを使ってアプリケーションを稼働させていることは「コンテナの中でアプリケーションが稼働していること」と等しい

イメージ

image.png
  • コンテナの雛形
  • 厳密には、アプリケーションの実行に必要なファイル群を格納するディレクトリ
  • 「イメージの中でアプリケーションが稼働している」という文脈はおかしい、コンテナと混合しないように注意

Dockerfile

  • インフラの構造をコードで管理するファイル

それぞれの関係

generative-relationship.png
  • コンテナからイメージを作ることができる
  • イメージからコンテナを作ることができる
  • Dockerfileからイメージを作ることができる

VMとDockerコンテナの違い

  • VM
    • 仮想ハードウェアの上にゲストOSがあってその上にアプリケーションがある
  • コンテナ
    • コンテナエンジンの上にアプリケーションがある
      • オーバーヘッドが少ない
    • カーネルを共有している
      • Linuxカーネルの技術を使用
        • cgroup
        • namespace
      • 分離されているもの(競合が起きない)
        • OSディストリブーション
        • IP
        • ファイルシステム
      • 分離されていないもの(競合が起きる)
        • オープンできるファイル数の上限
        • ファイル変更監視の上限数など

コンテナとVMの使い分け

  • コンテナ向け
    • システムの改変、開発が頻発
    • 比較的、可用性を厳密に求めない
  • VM向け
    • システムの改変をほとんど行わない
    • 可用性、信頼性、機密性が求められる

基本コマンド/コード

イメージ

  • イメージの検索

    • 「docker search <image>」
      • 実践1
        • $ docker search --filter "is-official=true" ubuntu
        • NAME                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
          ubuntu               Ubuntu is a Debian-based Linux operating sys…   12642     [OK]       
          websphere-liberty    WebSphere Liberty multi-architecture images …   277       [OK]       
          ubuntu-upstart       Upstart is an event-based replacement for th…   113       [OK]       
          ubuntu-debootstrap   debootstrap --variant=minbase --components=m…   44        [OK]       
          
      • オプション
        • 「--filter “condition”」
  • イメージの取得

    • 「docker image pull <image>:<tag>」
      • 補足
        • 「<tag>」をつけないと自動的に「latest」として取得される
      • 実践2
        • $ docker image pull ubuntu
        • Using default tag: latest
          latest: Pulling from library/ubuntu
          Digest: sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3
          Status: Image is up to date for ubuntu:latest
          docker.io/library/ubuntu:latest
          
  • イメージの一覧を表示

    • 「docker image ls」
      • 実践3
        • $ docker image ls
        • REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
          ubuntu       latest    1318b700e415   3 weeks ago   72.8MB
          
      • オプション
        • 「--no-trunc」
        • 「-q」
  • イメージの削除

    • 「docker image rm <image>:<tag>」
      • 実践4
        • $ docker image rm ubuntu:latest
        • Untagged: ubuntu:latest
          Untagged: ubuntu@sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3
          Deleted: sha256:1318b700e415001198d1bf66d260b07f67ca8a552b61b0da02b3832c778f221b
          Deleted: sha256:7555a8182c42c7737a384cfe03a3c7329f646a3bf389c4bcd75379fc85e6c144
          
      • オプション
        • 「-f」
          • (停止中の)コンテナのもとになっているイメージを消去する
            • 起動中は強制削除してもイメージは残る

コンテナ

  • コンテナの起動

    • 「docker container run <image>」
      • オプション
        • 「-i」
          • コンテナの STDIN にアタッチして標準入力を受け付けるようにする
        • 「-t」
          • 擬似ターミナルを割り当てる
        • 「--name」
          • コンテナに名前を付ける
            • 使用されているコンテナ名を指定するとエラーになる
        • 「--rm」
          • 停止すると自動でコンテナを削除する
        • 「-h」
          • ホスト名指定
            • ホスト名を指定しない場合、コンテナIDがホスト名になる
        • 「--mount type=<type>,src=<src>,dst=<directory_in_the_container>」
          • マウントする
            • 「<src>」と「<directory_in_the_container>」は絶対パス
            • タイプ(「<type>」)の種類
              • 「bind」
                • ホストOS上の任意のデバイスファイルやディレクトリをコンテナに共有する
                • 「<src>」はコンテナに共有するためのホストOS上のディレクトリ
              • 「volume」
                • ホストOS上のDockerで管理されるボリュームをコンテナに提供する
                • 「<src>」はホスト上の「/var/lib/docker/volumes」に作成されるボリューム名
                • 作成されたボリュームは別のコンテナでもマウントすることができるのでコンテナ間でストレージを共有するときに便利
              • 「tmpfs」
                • ホストOSのメモリの一部をファイルシステムとしてコンテナに提供する
                • 「src=<srv>」の部分は消去する
                  • 「--mount type=<type>,dst=<directory_in_the_container>」
                • スループットを増やしたい場合に有効
      • 実践5
        • 実践2を実行
          • $ docker image pull ubuntu
        • $ docker container run -it ubuntu echo "Hello, World!"
        • Hello, World!
          
  • コンテナの一覧を表示

    • 「docker container ls」
      • オプション
        • 「-a」
          • 停止しているコンテナを含む全コンテナの一覧を表示
      • 実践6
        • 実践5の実行直後はコンテナのシェルを使っているので$ exitを実行して抜ける
        • $ docker container ls -a
        • CONTAINER ID   IMAGE     COMMAND                 CREATED          STATUS                      PORTS     NAMES
          14597dd0d1cf   ubuntu    "echo 'Hello, World!'"   10 seconds ago    Exited (0) 10 seconds ago              confident_booth
          
  • コンテナの削除

    • 「docker container rm <name or container ID>」
      • 補足
        • 「docker container prune」は停止中の全コンテナを削除できる
      • 実践7
        • 使用中のコンテナIDが14597で始まることを実践6で確かめたので$ docker container rm 14597を実行する
  • コンテナ起動+ログイン

    • 「docker container run -it --name <name> -h <host name> <image> <command>」
      • 実践8
        • $ docker container run -it --name ubuntu_container -h host_name ubuntu /bin/bash
        • root@host_name:/#
          
  • ログイン中のコンテナから離脱

    • 「exit」
      • コンテナが停止する
    • 「Ctrl + p」 のあとに 「Ctrl + q」を入力
      • コンテナが停止しない
  • コンテナの作業ログ表示

    • 「docker container logs <name>」
      • 実践9
        • 実践8の実行直後はコンテナのシェルを使っているので、そこで$ lsを実行
        • Ctrl + p のあとに Ctrl + qを入力して抜ける
        • $ docker container logs ubuntu_container
        • root@host_name:/# ls  
          

          bin dev home lib32 libx32 mnt proc run srv tmp var boot etc lib lib64 media opt root sbin sys usr

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

    • 「docker container commit <name> <image>:<tag>」
      • 実践10
        • $ docker container commit ubuntu_container ubuntu:ubuntu_for_test
          • 例では「<name>」に「ubuntu」を使用しているが、新しくイメージの名前をつけてもいい
        • sha256:e86a0daaf4f6d350b4bcabe1973ffdd66fc3882aac69c99f1f561df780b3d86b
          
  • コンテナの消去

    • 「docker container rm <name or container ID>」
      • オプション
        • 「-f」
          • 起動中のコンテナも強制的に消去する
      • 実践11
        • $ docker container rm -f ubuntu_container
        • ubuntu_container
          
  • 停止中コンテナの起動

    • 「docker container start <name>」
      • 補足
        • 「docker container run」 コンテナを作成するときに「-it」 プションをつけている場合、このコマンドを実行したとき起動したままになる
      • 実践12
        • 実践8を実行
          • $ docker container run -it --name ubuntu_container -h host_name ubuntu /bin/bash
        • 実践8の実行直後はコンテナのシェルを使っているので$ exitを実行して抜ける
        • $ docker container start ubuntu_container
        • ubuntu_container
          
  • 起動中のコンテナにログイン

    • 2つ存在する
      • 「docker container attach <name>」
        • 補足
          • ログイン中に「exit」を実行して抜けるとコンテナが終了する
        • 実践13
          • $ docker container attach ubuntu_container
          • root@host_name:/#
            
      • 「docker exec -it <name> /bin/bash」
        • 補足
          • ログイン中に「exit`を実行して抜けてもコンテナが終了しない
        • 実践14
          • 実践13の実行直後はコンテナのシェルを使っているのでCtrl + p のあとに Ctrl + qを入力して抜ける
          • $ docker exec -it ubuntu_container /bin/bash
          • root@host_name:/#
            
  • 起動中のコンテナでコマンド実行

    • 「docker container exec -it <name> <command>」
      • 実践15
        • 実践14の実行直後はコンテナのシェルを使っているのでCtrl + p のあとに Ctrl + qを入力して抜ける
        • $ docker container exec -it ubuntu_container ls
        • bin   dev  home  lib32 libx32 mnt  proc  run  srv  tmp  var
          boot  etc  lib  lib64 media opt  root  sbin  sys  usr
          
  • コンテナの情報を表示

    • 「docker container inspect <name>」
      • 補足
        • 環境変数やIPアドレスなどを確認することができる
      • 実践16
        • $ docker container inspect ubuntu_container
        • 出力は長いので割愛
  • コンテナのリソース確認

    • 「docker container stats <name>」
      • 実践17
        • $ docker container stats ubuntu_container
        • CONTAINER ID   NAME               CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O   PIDS
          82aa1525801c   ubuntu_container   0.00%     820KiB / 1.942GiB   0.04%     1.44kB / 0B   0B / 0B     1
          
  • ホストOSとコンテナ間のファイルやディレクトリのコピー

    • 「ホストOSからコンテナへのコピー」と「コンテナからホストOSへ」の2パターンの処理があり、「コンテナから別のコンテナへのコピー」はできない
      • ホストOSからコンテナへのコピー
        • 「docker container cp <path_in_host_os> <name>:<directory_in_container>」
          • 実践18
            • 実践17の実行後のプロセスは持続的に実行されるのでCtrl+cで停止する
            • $ touch hoge.txtを実行
            • 「ubuntu_container」コンテナの中に入って「workspace」ディレクトリを作り、コンテナが停止しないようにコンテナから出る
            • $ docker container cp ./hoge.txt ubuntu_container:workspace/
      • コンテナからホストOSへのコピー
        • 「docker container cp <name>:<path_in_container> <directory_in_host_os>」
          • 実践19
            • カレントディレクトリにある「hoge.txt」を削除
            • $ docker container cp ubuntu_container:workspace/hoge.txt ./

Dockerfile

  • 基本コード
    • 「FROM <image>:<tag>」
      • ベースイメージを指定
      • 「<tag>」は省略可能
    • 「LABEL <key>=<value>」
      • Dockerのイメージにメタデータを追加
        • メタデータ
          • この場合、開発者情報やバージョン、概要など
    • 「ENV <key> <value>」
      • 環境変数を設定
    • 「RUN <command>」
      • イメージのビルド中にコマンドを実行
    • 「COPY <path> <directory>」
      • ファイルとディレクトリをコンテナにコピー
        • 対象のファイルはローカル上にある
        • コピーの際に圧縮ファイルを解凍しない
    • 「ADD <path> <directory>」
      • ファイルとディレクトリをコンテナにコピー
        • 対象のファイルはリモート上にある
        • コピーの際に圧縮ファイルを解凍する
        • アンチパターンが多いので注意
    • 「WORKDIR <directory>」
      • 作業ディレクトリを指定
    • 「ENTRYPOINT [<command>, <arg1>, <arg2>, …]」
      • イメージからコンテナを作成したときにコマンドを実行
        • 複数回このコードを使うことはできない
        • 引数がオーバーライドできない
    • 「CMD [<command>, <arg1>, <arg2>, …]」
      • 完成したイメージからコンテナを作成するときにコマンドを実行
        • 複数回このコードを使うことはできない
        • 引数がオーバーライドできる
    • その他
      • 「ARG」
        • ビルド時にDockerに渡す変数を定義
      • 「EXPOSE」
        • ポートを公開
      • 「VOLUME」
        • マウントポイントを作成して、ホストや他のコンテナからボリュームのマウントを行う
    • 例1
      • FROM ubuntu
        LABEL maintainer="Yoshisaur" version="1.0" description="Ubuntu with Vim"
        ENV MES=vim-was-successfully-installed
        RUN mkdir workspace
        COPY hoge.txt /workspace/
        WORKDIR /workplace
        RUN apt update &&\
            apt -y upgrade &&\
            yes | apt install vim &&\
            echo $MES > ./hoge.txt &&\
            which vim >> ./hoge.txt
        ENTRYPOINT ["/bin/bash"]
        
      • 解説
        • 「FROM ubuntu」
          • 「ubuntu:latest」を元にイメージ作成
        • 「LABEL maintainer=“hoge” version=“1.0” description=“Ubuntu with Vim”」
          • 「maintainer」, 「version」, 「description」に関するメタデータを追加
            • 「docker image inspect」コマンドでメタデータを見ることができる
              • 「--format」オプションを付けることで「LABEL」で追加したメタデータのみ表示することができる
        • 「ENV MES=vim-was-successfully-installed」
          • 環境変数として「MES」に「vim-was-successfully-installed」代入
        • 「RUN mkdir workspace」
          • 「workspace」というディレクトリを「/」で作成
        • 「COPY hoge.txt /workspace/」
          • ローカルにある「hoge.txt」をコンテナの「/workspace/」にコピー
        • 「WORKDIR /workplace」
          • 作業ディレクトリを「/workspace」にする
        • 「RUN」
          • 「apt update &&\」
            • パッケージのリポジトリから、パッケージの名前やバージョン、依存関係を取得し、有効でインストール可能なパッケージの一覧を更新
          • 「apt -y upgrade &&\」
            • 有効なパッケージ一覧を元に、アップデート可能なパッケージを更新
          • 「yes | apt install vim &&\」
            • Vimをインストール
          • 「echo $MES > ./hoge.txt &&\」
            • 「vim-was-successfully-installed」という値を持つ環境変数「MES」を出力して、コンテナ内の「hoge.txt」の中身にする
          • 「which vim » ./hoge.txt」
            • Vimのパスを「hoge.txt」の一番下の行に追加する
        • 「ENTRYPOINT ["/bin/bash"]」
          • コンテナを作成したときに、「/bin/bash」を実行してコンテナ内でbashシェルを立ち上げる
          • デーモンプロセスを立ち上げるのに適している
  • イメージのビルド
    • 「docker build <options> <path>」
      • 「<options>」
        • 「--no-cache」
          • ビルドにキャッシュを使わない
        • 「-f <Dockerfile>」
          • 使用するDockerfileを指定
          • 指定がない場合「<path>/Dockerfile」が使用される
        • 「-t <image>:<tag>」
          • ビルドして作成されるイメージに付与するイメージとタグ
      • 「<path>」
        • ビルドで使用するファイルが保存されている場所
      • 実践20
        • 中身が例1の「Dockerfile_ubuntu_with_vim」という名前のファイルを用意
        • $ docker image build --no-cache -f ./Dockerfile_ubuntu_with_vim -t ubuntu:image_from_dockerfile .
        • [+] Building 77.1s (10/10) FINISHED                                                                                                    
            => [internal] load build definition from Dockerfile_ubuntu_with_vim                                                              0.1s
            => => transferring dockerfile: 53B                                                                                               0.0s
                  => [internal] load .dockerignore                                                                                                 0.0s
            => => transferring context: 2B                                                                                                   0.0s
            => [internal] load metadata for docker.io/library/ubuntu:latest                                                                  0.0s
            => CACHED [1/5] FROM docker.io/library/ubuntu                                                                                    0.0s
            => [internal] load build context                                                                                                 0.0s
            => => transferring context: 29B                                                                                                  0.0s
            => [2/5] RUN mkdir workspace                                                                                                     0.3s
                  => [3/5] COPY hoge.txt /workspace/                                                                                               0.0s
            => [4/5] WORKDIR /workplace                                                                                                      0.0s
            => [5/5] RUN apt update &&    apt -y upgrade &&    yes | apt install vim &&    echo vim-was-successfully-installed > ./hoge.tx  75.5s
                  => exporting to image                                                                                                            1.1s
            => => exporting layers                                                                                                           1.1s
            => => writing image sha256:45735f63fc2f671292ebd608807547eaf779ba91bed6fbbbd9d68943bf4bbf0d                                      0.0s 
            => => naming to docker.io/library/ubuntu:image_from_dockerfile 
          
        • 実践11を実行
          • $ docker container rm -f ubuntu_container
        • $ docker container run -it --name ubuntu_container -h host_name ubuntu:image_from_dockerfileを実行
        • コンテナ内の「/workspace/hoge.txt」の中身が以下のようになっていることを確認
          • vim-was-successfully-installed
            /usr/bin/vim
            
  • マルチステージビルド
    • Dockerfile
      • 「FROM」を複数使う
      • 例2
        • #Stage 1
          FROM golang AS build01
          RUN mkdir workspace
          COPY ./hello_world.go /workspace/
          WORKDIR /workspace
          RUN go build hello_world.go
          #Stage 2
          FROM ubuntu
          RUN mkdir workspace
          COPY --from=build01 workspace/hello_world /workspace
          WORKDIR /workspace
          ENTRYPOINT ["./hello_world"]
          
        • 解説
          • 2つのステージに分けて定義をしている
            • ステージ1
              • 「FROM golang AS build01」
                • 「build01」として「latest」の「golang」を元にイメージを作成
              • 「RUN mkdir workspace」
                • 「workspace」というディレクトリを「/」で作成
              • 「COPY ./hello_world.go /workspace/」
                • ローカルにある「hello_world.go」をステージ1の「/workspace/」にコピー
              • 「WORKDIR /workspace」
                • 作業ディレクトリを「/workspace」にする
              • 「RUN go build hello_world.go」
            • ステージ2
              • 「FROM ubuntu」
                • 「ubuntu:latest」を元にイメージ作成
              • 「RUN mkdir workspace」
                • 「workspace」というディレクトリを「/」で作成
              • 「COPY –from=build01 workspace/hello_world /workspace」
                • ステージ1である「build01」で生成した「hello_world」というシングルバイナリを「workspace」にコピー
              • 「WORKDIR /workspace」
                • 作業ディレクトリを「/workspace」にする
              • 「ENTRYPOINT ["./hello_world"]」
                • コンテナを作成したときに「./hello_world」を実行する
          • 流れ
            • ステージ1でgolangのシングルバイナリを生成する
            • ステージ2にステージ1で生成したシングルバイナリを渡す
            • ステージ2でシングルバイナリを実行する
          • 利点
            • 最終的に作成されるイメージはステージ2であるため、ステージ1にあるgolangのコンパイラや「hello_world.go」ファイルをイメージに含む必要がないので軽量化になる
    • イメージのビルド
      • 実践21
        • ローカルで「hello_world.go」を用意
          • 中身
            • package main
              import "fmt"
              func main() {
                  fmt.Println("Hello, World!")
              }
              
        • 中身が例2の「Dockerfile_ubuntu_with_a_go_binary」という名前のファイルを用意
        • $ docker image build --no-cache -f ./Dockerfile_ubuntu_with_a_go_binary -t ubuntu:image_from_dockerfile_using_multi_stage_multi_stage_builds .
        • 実践11を実行
          • $ docker container rm -f ubuntu_container
        • $ docker container run -it --name ubuntu_container -h host_name ubuntu:image_from_dockerfile_using_multi_stage_multi_stage_buildsを実行
        • Hello, World!
          
comments powered by Disqus