Dockerはソフトウェアコンテナ内のアプリケーションのデプロイメントを自動化するオープンソースソフトウェアである。LinuxカーネルにおけるLXCと呼ばれるLinuxコンテナ技術とAufsという特殊なファイルシステムを利用してコンテナ型の仮想化を行う。(Wikipedia)
すでに Docker の位置づけは変わってきている。基礎となる部分も LXCから containerd.io と呼ばれる高レイヤーコンテナーエンジンとなっており、LXC時代よりも安定・高速化した(このcontainerd.ioはすでにdockerからは独立したプロジェクトになっている)。また Kubernetesの登場によってネットインフラにおけるコンテナエンジンとしては Docker以外にも多くの技術が登場しており、それぞれが特徴を持って開発されている。しかし公開されているフリーのコンテナエンジンとしての歴史も利用者も多いため、未だに多くの利用者が活用している。
他の仮想化との大きな違いは、厳密にはハード(xen,kvm)などの仮想化などと違い、あくまでホストOSのプロセスの1つとして動作し、chrootのようなファイルアクセス範囲の制限などで、ゲストOSを1つの環境に見立てているため、論理上のハードウェアエミュレーションのような、オーバーヘッドがほとんど存在しない。
<特に注意するべき点>
dockerは環境をソースのような形で定義できるようにすることで、メンテナンス性を高めており、複雑化した環境設定を視覚化している。そのためコンテナという概念は、サブバージョンのような、更新履歴の概念で管理され、一般的な仮想化システムにおけるゲストOSのような概念ではない。
ようするに、コマンドを実行するたびに、コンテナを作成していくことで、環境変更の履歴がすべて、コンテナとして残る。また、そのコンテナから新しいコンテナと実行コマンドを指定して、さらにコンテナを作成し、それらを繰り返し後、すべての環境が設定された時点で、commit してコンテナイメージとして作成し配布イメージとする。
もちろん、最初のコンテナ作成時にシェルを指定して、通常の仮想化システムのように、シェルを通じて環境を整備することも可能だが、それらの環境整備の履歴は当然のこらないので、出来上がったコンテナのみを使いまわすことになる。
ここでは、Centos7 をベースとする。基本は yum で下記のようにインストールする。
# yum install docker
<起動>
# systemctl enable docker # systemctl start docker
<確認>
# docker info
コンテナイメージの作成は、Dockerfile に記述し、それをビルドすることで実現できる。
このファイルでは、下記の指定ができる。
命令 | 用途 |
FROM | 元となるDockerイメージの指定 |
MAINTAINER | 作成者の情報 |
RUN | コマンドの実行 |
ADD | ファイル/ディレクトリの追加 |
CMD | コンテナーの実行コマンド |
ENTRYPOINT | コンテナーの実行コマンド |
WORKDIR | 作業ディレクトリの指定 |
ENV | 環境変数の指定 |
USER | 実行ユーザーの指定 |
EXPOSE | ポートのエクスポート |
VOLUME | ボリュームのマウント |
<例>
# vi Dockerfile FROM centos:latest <- 元イメージ必須。 RUN yum install -y wget
# docker build -t <イメージファイル名> ./ <- 最後の指定はdockerfileのあるフォルダを指定
<ビルドの確認>
#docker images
<イメージ削除>
# docker rmi <イメージファイル名>
※<イメージファイル名>は、ユーザー名/イメージファイル名 で構成される。ただしトップレベルイメージは別。
docker hubからすでに作成済みのdocker コンテナイメージをダウンロードできる。ちょっとしたツールのテストなどでは、重宝する。
# docker pull <イメージファイル名>:<tag>
基本的にはイメージファイル名は、投稿したユーザー名/イメージファイル名で構成されるが、centos のように、トップレベルリポジトリのものは、投稿したユーザー名が無い場合がある。
<ダウンロードしたコンテナイメージの一覧表示>
# docker images
通常の仮想化のように、利用するのであれば、centos などコンテナイメージなどをダウンロードして、実行されるだけでよい。
# docker pull centos:latest # docker run -it --name centos_image01 centos:latest /bin/sh
イメージIDでも良い。d オプションはデタッチモード。コンテナが実行するルート・プロセスが終了したら、デタッチド・モードで起動したコンテナも終了する。
# docker run -itd <image id> /bin/sh
これで、centos:latest というコンテナイメージから、centos_image01 という新しいコンテナが起動し、/bin/sh を起動するので、コンテナのコンソールとして、新しいコマンドプロンプトが表示される。この場合、コンテナのコマンドプロンプトからホストOSに戻る場合は、ctrl + D で起動時に指定したプログラム(上記の場合 /bin/sh )が終了するため元のホストOSのコンソールに戻れる。(同時に作成されたコンテナも停止状態になる)
参考までに Docker hub に登録されているイメージの情報を取得するのはいかの通り。
# docker search <キーワード>
オプション -v <ホストのフォルダ位置>:<コンテナのフォルダ位置> で指定できる。
<例>
# docker run -it -v /usr/local/src:/src centos /bin/sh
ただしこの場合、read-only となる。書き込みを許可する場合には、さらに --privileged オプションを指定する。
# docker run --privileged -it -v /usr/local/src:/src centos /bin/sh
オプション -p host_port:conteiner_port
<例>
# docker run -it -p 8080:80 centos /bin/sh
# docker ps -a (-a を指定しないと実行中のみ、-q だとIDのみスクリプトに便利)
# docker exec -it centos_image01 /bin/sh
※停止中のコンテナは、すでにコンテナとして実行終了しているので、exec コマンドでは、命令をコンテナに与えられない。
<一時停止(StatusがUpのものだけ)>
# docker pause <コンテナ名>
<一時停止の解除(STATUSが pauseのものだけ)>
# docker unpause <コンテナ名>
<コンテナの停止(shutdown:StatusがUpのものだけ)>
# docker stop <コンテナ名>
<コンテナの再起動(Statusが、Exited (-1)のものだけ)>
# docker restart <コンテナ名>
<コンテナの削除>
# docker rm <コンテナ名>
<コンテナの全削除>
# docker rm $(docker ps -aq)
<dockerイメージの削除> ※docker images で確認できる
# docker rmi <IMAGE ID>
<ログ表示>
# docker logs <コンテナ名>
<起動中のコンテナのコンソールに接続> 上記の exec の方が使いやすい
# docker attach <コンテナ名>
※注意:現在のコンソールと、コンテナのコンソールを接続するが、キーコントロールが入力できないので、元のホストのコンソールに戻ってこれなくなる。他のシェルを起動して、doccker stop でコンテナを停止させると、戻ってくる。
<コンテナの詳細表示>
# docker inspect <コンテナ名>
<docker networkの状態>
# docker network ls
<コンテナからコンテナイメージの作成>
# docker commit <コンテナ名> <ユーザー名/イメージファイル名>
※上記にあるように、ユーザー名/ をイメージファイル名の頭につけること。
<コンテナイメージをdockerサイトのリポジトリに登録>
# docker push <ユーザー名/イメージファイル名>
※公開されてしまうので、pushは十分に注意の上実行
# curl -L -O https://github.com/hadolint/hadolint/releases/download/v1.15.0/hadolint-Linux-x86_64 # mv hadolint-Linux-x86_64 hadolint # chmod +x hadolint
これでチェック可能
# hadolint ./Dockerfile
<ADD,COPY ではホスト側のフォルダ指定に絶対パスを指定してはならない>
ADD /usr/docker/containers/xxxx.txt /var/www/html/xxxx.txt
これはコピーされずにエラーになる。
<また相対パスでも ADDやCOPYの場合は、Dockerfile のあるフォルダとその下位のフォルダしか参照できない。よって上位フォルダやそこを経由したのアクセスができない>
ADD ../test2/test.txt /usr/test.txt <- このような .. 指定は使えない。
そのため、docker-compose.yml の build指定 で context の位置を明示的に指定し、Dockerfile の場所も明示することで、build のカレントを docker-compose.yml で指定できる。これによって Dockerfile のADD, COPY 指定においても context からの相対になる。
# vi docker-compose.yml version: '3' services: web: build: context: . <-- docker-compose.yml のカレントフォルダ位置 dockerfile: ./web/Dockerfile <-- Dockerfile は、contextからの相対指定 ....
カレントフォルダにある docker-compose.yml を実行する。(コンソールが占有されるがログは垂れ流される)
# docker-compose up
※consoleがlog表示モードになって操作できなくなる。
デーモンオプションをつけてバックグランドで起動する。
# docker-compose up -d
実行にあわせてビルドも一緒に行う
# docker-compose up -d --build
Logの最新20行を表示
# docker-compose logs --tail="20" -t
停止&削除(コンテナ・ネットワーク)※docker ps から消える
# docker-compose down
停止&削除(コンテナ・ネットワーク・イメージ)※ビルドされたイメージだけでなく、docker hub から pull したイメージも消える。
# docker-compose down --rmi all <- allの代わりに local だと作成したイメージのみ削除
停止&削除(コンテナ・ネットワーク・ボリューム)
# docker-compose down --rmi all --volumes
docker-compose.yml に version: '3' が漏れている。