#1.Dockerのインストール#
##1-1Docker Desktop for 〇〇をダウンロードし、インストールする##
Docker Desktop for Mac
Docker for Mac で Dockerコンテナを実行する場合、MacOSで直にコンテナが動作するのではなく、HyperKitというMacの仮想化機能を利用して内部的には軽量のLinuxを動作させ、その上でDockerコンテナを実行します。
本編は、Docker Desktop for Mac を利用していますが、基本的なDockerコマンドなどの使い方はWindowsも同じです。
Windowsをお使いの場合は、Windows Docker Desktop for Windowsを利用してください。
#2.Dockerコンテナの実行#
##2-1 hello-worldを動作させてみよう##
とりあえず、hello-worldイメージを実行し、コンテナを動かして見ましょう。
docker run hello-world
初回は、インターネット経由でDocker HubからDockerイメージをダウンロードしてきます。
同じDockerイメージがPC上に存在する場合は、②③が省略され、ローカル上にあるDockerイメージからDockerコンテナが実行されます。
:
でタグを指定できます。指定が何もない場合は、latest(最新)となります。
下記のように実行してみましょう。ただし、実行結果は「2-1.hello-worldを動作させてみよう」と同じ結果になります。
docker run hello-world:latest
##2-2 Dockerイメージ##
Dockerイメージとは、コンテナの実行に必要なファイルを纏めたファイルシステムです。
一度作成したイメージのレイヤーは、「読み取り専用」となり変更を加えることはできません。
コンテナレイヤー上にファイルの追加や削除を行い、それをまたDockerイメージとして保存することも可能です。
whalesayイメージを実行し、Helloと喋らせてみましょう。
docker run docker/whalesay cowsay Hello
Unable to find image 'docker/whalesay:latest' locally
latest: Pulling from docker/whalesay
e190868d63f8: Pull complete
909cd34c6fd7: Pull complete
0b9bfabab7c1: Pull complete
a3ed95caeb02: Pull complete
00bf65475aba: Pull complete
c57b6bcc83e3: Pull complete
8978f6879e2f: Pull complete
8eed3712d2cf: Pull complete
Digest: sha256:178598e51a26abbc958b8a2e48825c90bc22e641de3d31e18aaf55f3258ba93b
Status: Downloaded newer image for docker/whalesay:latest
_______
< Hello >
-------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
ローカル上にダウンロード済みのDockerイメージの一覧を表示させてみましょう。
docker images
Dockerイメージにタグ付けすることも可能です。
docker tag docker/whalesay whalesay:v1
コンテナの情報を取得してみましょう。
docker inspect docker/whalesay
作成したdocker/whalesayを削除してみましょう。
なお、dockerが起動しているときにDockerイメージを削除することはできません。
dockerが起動しているときに、強制的にDockerイメージを削除する場合は、docker rmi の後に -f
をつけることによって、強制的に削除することも可能ではあります。(下記の例では、-f は使っていません。)
docker rmi docker/whalesay
Dockerイメージを削除したので、Dockerコンテナは実行せず、Dockerイメージをダウンロードだけするには、pullします。
docker pull docker/whalesay
##2-3 Dockerファイル##
先程は、DockerイメージをDocker Hubから取得してきましたが、Dockerファイルを作成してビルドすることも可能です。
まず、作業用のフォルダを作成しておきましょう。
mkdir imagebuild
cd imagebuild
下記のとおり、Dockerfileを作成します。
FROM docker/whalesay:latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune | cowsay
## FROM : ベースイメージの指定
## RUN : コマンド実行
## CMD : デーモン実行
作成したDockerfileファイルからイメージをビルドするには以下のコマンドを実行します。-t
はタグの指定です。
docker build -t docker-whale .
ビルドしたイメージを実行して見ましょう。
docker run docker-whale
________________________________________
/ As the trials of life continue to take \
| their toll, remember that there is |
| always a future in Computer |
| Maintenance. |
| |
\ -- National Lampoon, "Deteriorata" /
----------------------------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
ちなみに2回目以降、キャッシュをを使用せずビルドするには、以下のように実行します。
docker build --no-cache -t docker-whale .
次に自身で作成したDockerイメージをDockerHubに公開して見ましょう。
[DockerHub]の Repository に docker-whale を作成しておいてください。
Docker Hubにログインします。
docker login
タグをつけておきます。
docker tag docker-whale <Docker ID>/docker-whale:v1
DockerイメージをDockerHubにPushし、DockerHubにあることを確認しましょう。
docker push <Docker ID>/docker-whale:v1
##2-4 デタッチモード(-d)##
-d
はデタッチモードといい、コンテナの実行をバックグラウンドで行うものです。
docker run --name nginx-d1 -d -p 8080:80 nginx
http://localhost:8080/
にアクセスすると表示されると思います。
なお、-p
の動作について図で簡単に見ておきましょう。
localhost:8080はコンテナのPort:80に転送するという意味です。
-d
をつけない場合との動作の違いを確認しておきましょう。
docker run --name nginx-d2 -p 8080:80 nginx
http://localhost:8080/
にアクセスして見ましょう。
WEBページの表示は変わりませんが、WEBページにアクセスした際、↓のようにログが画面に流れていることがわかります。
172.17.0.1 - - [03/Jul/2019:10:38:14 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
172.17.0.1 - - [03/Jul/2019:10:38:22 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-"
この状態ではフォアグラウンドで動作しているので、ctrl+C
でプロセス終了した場合、コンテナも停止されてしまうという違いがあります。
そのため、WEBページなどは基本デタッチモードで動作させるようします。
##2-5 マウント(-V)##
ホストマシンにあるディレクトリをコンテナ上にマウントしてみましょう。
私はMacを利用しています。まずは、/Users/<ユーザ名>/docker/html
にindex.htmlを作成しておきます。
<!DOCTYPE html>
<html>
<body>
<h1>hellow</h1>
</body>
</html>
では、マウントしてみましょう。
docker run --name nginx-m1 -v /Users/<ユーザ名>/docker/html:/usr/share/nginx/html:ro -d -p 8080:80 nginx
http://localhost:8080/
にアクセスし表示されるか確認しましょう。
表示されたことが確認できたら、/Users/<ユーザ名>/docker/html/index.htmlの内容を編集し、編集内容が反映されているかも再度アクセスして確認してみましょう。
##2-6 コピー(copy)##
COPYコマンドはホストマシン↔︎コンテナ内にコピーするコマンドです。
Dockerコンテナを用意しておきます。
docker run --name nginx-c1 --rm -d nginx
作業しやすいように、copyディレクトリを作成しておきます。
mkdir copy
cd copy/
copyコマンドで設定ファイルを取り出してみます。先程作成したnginx-c1の中にあるdefault.confを取り出します。lsでコピーされたかも確認しておいてください。
docker cp nginx-c1:/etc/nginx/conf.d/default.conf ./
ls
ここでは、動作検証のためにわざとlisten:8080に変え、→ DockerFileを作成し、→ ビルドします。
listen:8080
## 80→8080に変更する。
FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/default.conf
docker build -t nginx:c2 .
Dockerコンテナをlisten:80で実行しますが、これは先程default.confをlisten:8080に変更したのでアクセスできません。
docker run --name web -p 8080:80 --rm nginx:c2
8080番ポートだと、アクセスできるようになりました。
docker run --name web -p 8080:8080 --rm nginx:c2
##2-7 Dockerの基本コマンド##
i
はコンテナの標準入力を取得して、双方向に接続できるようにするもので、
t
はコンテナ内にttyを割り当てる意味があります。
コンテナでシェルを実行して、フォアグラウンドで実行状態にしておきたい場合はよく使われます。
docker create --name c-container -it alpine /bin/sh
コンテナの一覧を表示させるコマンドです。
docker ps 実行中のコンテナを表示する。
docker ps -a 実行中以外のコンテナも表示する。
その他、Dockerを開始や停止するコマンドです。
docker start 開始
docker stop 停止
docker pause 一時停止
docker unpause 一時停止を解除
##2-8 シェルへの接続(attach,exec)##
起動中のコンテナに接続する方法を確認して行きましょう。2通りあります。
attach
exec
☆推奨
とりあえず、Dockerコンテナを起動します。
docker run --name shell-1 -it ubuntu /bin/bash
まずは、attach
で接続して、exitで抜けてみます。
attachで接続し、exitで抜けた場合は、プロセスが終了し、コンテナも終了されてしまうので注意が必要です。
基本的にはctrl+p ctrl+qでぬけることで、コンテナも終了せずにできます。
ただし、起動時に-itをつけていない場合は、ctrl+p ctrl+qでぬけることができません。
docker attach shell-1
exit
次に、exec
で接続し、同じようにexitで抜けてみましょう。
この場合は、exitで抜けてもコンテナは起動したままの状態です。
そのため、基本的にはexecで接続するようにします。
docker exec -it shell-1 /bin/bash
exit
##2-9 docker commit##
commitコマンドは、コンテナに対して行った設定や更新したファイルを、新しいDockerイメージとして格納することが出来ます。
ただし、コンテナ内で行われた作業はどこにも明確な記録として残らないため、極力「2-3 Dockerファイル」を使うようにしましょう。
Dockerコンテナを作成しておきます。
docker run --name commit-1 -it -d --rm ubuntu /bin/bash
このDockerコンテナに、何かしらの変更をしておきます。
docker exec -it commit-1 /bin/bash
cd /tmp/
dd if=/dev/zero of=tempfile bs=1M count=10
exit
commit-1をcommit-2としてコミットし、→ 新しいDockerコンテナを起動すると完了です。
docker commit commit-1 commit-2
docker run -it commit-2 /bin/bash
##2-10 リンク(--link)##
コンテナ名、またはエイリアスでリンク先に通信できるようにします。
ただし、--linkオプションはすでに非推奨ですので、後述の「Dockerのネットワーク」を主に学習してください。
なので、ここでは--linkオプションについては簡単な操作だけ行います。
作業用のproxyというフォルダを作成しておきましょう。
mkdir proxy
cd proxy
reverse_proxy.conf を作成しておきます。
server {
listen 8080
server_name localhost;
location / {
proxy_pass http://ss;
}
}
先程作成したreverse_proxy.confを使い、Dockerfileを作成します。
FROM nginx:latest
COPY /reverse_proxy.conf /etc/nginx/conf.d/reverse_proxy.conf
RUN apt-get update && apt-get install -y inetutils-ping
proxyという名前でDockerfileをビルドします。
docker build -t proxy .
dockersamples/static-siteのdockerコンテナを実行します。
docker run --name website -e AUTHOR="naata" -d dockersamples/static-site
proxyのdockerコンテナを実行します。
docker run --name webproxy -p 8080:8080 --link website:ss -d proxy
websiteとwebproxyのdockerコンテナが起動していることを確認しておきます。
docker ps
http://localhost:8080
にアクセスして表示されるか確認してみましょう。これで、webproxyを経由して、websiteが表示されていることになります。
#3 Automated build#
Githubなどのソースコードのホスティングサービスでビルドテキストを管理し、リポジトリ上のビルドコンテキストを管理し、リポジトリ上のビルドコンテキストの内容が変更された場合に自動的にビルドを実行する仕組み。
##3-1 GitHub にレポジトリを作成##
GithubにDocker_Automated_build
というrepositoryを作成しておいてください。
##3-2 Dockerhub 設定##
自分のアカウントから[Account Settings]をクリック。
[Linked Accounts]のGitHubで[Connect provider]をクリック。
docker_repositoryをdocker_automated_build
で作成し、「3-1 GitHub にレポジトリを作成」で作成したgit_repositoryを選択する。
基本的な設定は以上なので、検証していきます。
##3-3 検証##
以下は通常のgit操作となりますので、詳しい説明は省略します。
git config --global user.name ""
git config --global user.email ""
git clone https://github.com/aaa/Docker_Automated_build
cd Docker_Automated_build/
FROM dockersamples/static-site
ENV AUTHOR="naata"
git add Dockerfile
git commit -m "First Automated"
git push origin master
DockerHubを確認し、SUCCESSとなっていればOK
念のため pull して確認もしておきましょう。
docker pull aaa/docker_automated_build
docker images
#4 Docker Machine#
##4-1 Docker Machine##
Docker Machineは、Docker for Mac / Docker for WindowsまたはDocker toolboxに付属してインストールされるソフトウェアです。
Docker Engineをインストールした仮想マシンの作成、起動、停止、再起動などをコマンドラインから実行することができるツールです。
##4-2 Dockerホストの作成##
単純にローカルPCにDockerホストを作成していきます。
docker-machine create --driver virtualbox default
作成されたか確認して見ましょう。
docker-machine ls
作成されたDockerホストに接続して見ましょう。操作対象のDockerホストを設定するための、設定コマンドが表示されます。
環境変数を設定すると、Docerコマンドの操作対象がenvの引数に指定したDockerホストに設定されます。
docker-machine env default
eval $(docker-machine env default)
確認のために、hello-worldコンテナを実行し見ましょう。
docker run hello-world
Dockerホストにsshすることもできます。
docker-machine ssh default
exitで抜けましょう。
exit
dockerホストのipを確認し、nginxを実行し、このipでwebページがかえってくるか確認して見ましょう。
docker-machine ip default
docker run -d -p 8080:80 nginx
docker-machine を明示的に停止、開始するには以下の通り指定します。
docker-machine stop default
docker-machine start default
activeなdocker-machineを解除するには。
docker-machine env -u
eval $(docker-machine env -u)
#5 Dockerのネットワーク##
「2-10 リンク(--link)」で紹介した--link
オプションは利用せず、ユーザー定義ネットワークを使う方法が推奨されています。
docker networkの一覧を表示すると、デフォルトで3つのネットワークがあることがわかります。
docker network ls
NETWORK ID NAME DRIVER SCOPE
3d43dcdb4080 bridge bridge local
8b1af105abd9 host host local
afffac7bcd1b none null local
##5-1 bridge##
コンテナはデフォルトでブリッジドライバーに所属します。
ブリッジネットワークの詳細を確認して見ましょう。
docker network inspect bridge
subnet → このネットワーク内のipが割り当てられる。
Getway → dockerホストのdocker0に割り当てられたI/Fとなります。
コンテナを2つ起動して見ましょう。
docker run -itd --name net1 alpine /bin/sh
docker run -itd --name net2 alpine /bin/sh
それぞれのコンテナにipが割り当てられたことを確認します。
docker inspect brige
コンテナ net1 ↔︎ net2 で疎通ができるか確認してみましょう。
ping <ip>
なお、デフォルトでdnsは提供されないため、コンテナ名で通信することはできません。そのため、ネットワークを追加します。
docker network create my_net
これに先ほどのコンテナ2台を追加します。
docker network connect my_net net1
docker network connect my_net net2
これで、 net1 ↔︎ net2 がコンテナ名で通信できるか確認してみましょう。
ping <コンテナ名>
ちなみに、最初からmy_netネットワークに所属させるためには以下のコマンドを使います。
docker run -itd --name net3 --network my_net alpine
また、ネットワークを切り離すには以下のとおり実行します。
docker network disconnect bridge net2
##5-2 none##
nullドライバに接続してコンテナは、ループバックI/F以外にネットワークI/Fを持たない状態になります。
また、noneネットワークを接続するコンテナは、その他の全てのネットワークを切断した状態にしなければいけません。
docker run -itd --name none1 --network none alpine /bin/sh
docker attach none1
ip addr show
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
##5-3 host##
hostドライバを使用したネットワークです。
hostネットワークに接続したコンテナはdockerホストと同じネットワーク設定を持ちます。
ホストネットワークのコンテナでwebサーバーを起動した場合、ホストマシンのipの80でlistenしているのと同じ動作になります。
そのため、-p を利用しなくても、コンテナを起動しただけで、dockerホストの80にアクセスすれば、コンテナの80に接続することができます。
docker run -d --name host --network host nginx
hostのipにアクセスして表示されるか確認だけしておきましょう。
#6 Dockerのデータ管理##
コンテナで扱う動的なデータは起動中のコンテナの読み書き可能なレイヤーにおくこともできますが、いくつかのデメリットがあります。
それは、
・コンテナが削除された時点でデータは消えてしまう。
・コンテナ間でデータを共有することができない。
・書き込みのパフォーマンスもホスト上へのデータの書き込みに加えて、書き込みのパフォーマンスがよくない。
これは、通常のファイルシステムとは異なるユニオンファイルシステムが利用されているためです。
dockerにはホスト上のディレクトリやファイルをコンテナにマウントする仕組みやホストのメモリをファイルシステムとしてコンテナにマウントする仕組みが用意されています。
##6-1 volume##
複数のコンテナにマウントすることもでき、複数のコンテナで共通のファイルを読み書きすることができます。
ただし、異なるホスト間で共有することはできません。
ボリュームはコンテナが削除されても消えず、明示的に削除するまで消えません。
まずは、docker volumeコマンドをいくつか覚えましょう。
docker volumeを作成するコマンドです。
docker volume create vol-1
一覧を表示するコマンドです。
docker volume ls
詳細情報を確認するコマンドです。
docker volume inspect vol-1
削除するコマンドです。
docker volume rm vol-1
ではここから、volumeをマウントする方法です。2つの方法があります。
-v
--mount
→ 基本的にこっちの方が推奨されているのでこっちで覚えましょう。
今回は-vでも試してみます。ここではまだvolumeがないのでvol2を作成ています。
docker run -itd --name mount1 -v vol2:/app nginx
--mountで試します。
docker run -itd --name mount2 --mount source=vol2,target=/app nginx
docker execで接続して、同じファイルがあるか確認しておきましょう。
docker exec -itd mount1 /bin/bash
cd /app
touch hogehoge
exit
docker exec mount2
cd /app
読み取り専用(readonly)にする場合は、以下のとおり実行します。
docker run -itd --name mount3 --mount source=vol3,destination=/etc/nginx,readonly nginx
##6-2 bind mount##
ホストが管理しているファイルやディレクトリをコンテナにマウントします。
これも2つの方法があります。
-v
--mount
→ 基本的にこっちが推奨されているのでこっちを使います。
-vでカレントディレクトリに存在しないディレクトをマウントします。
docker run -itd --name bindmount1 -v "$(pwd)"/source:/app nginx
lsでsourceディレクトリが作成されていることを確認しておきましょう。
ls
T632717CF0F94D06EE source
--mountを利用する場合は、type=bind
を指定します。
docker run -itd --name bindmount2 --mount type=bind,source"$(pwd)"/source2,target=/app nginx
エラーになったと思います。
--mountではディレクトが存在しない場合はエラーになります。これにより謝って空のディレクトリをマウントしてしまわないことを防ぎます。
##6-3 tmpfs##
ホストのメモリ領域をマウントします。ホストやDockerがシャットダウンされた場合は、データは消えます。なので、一時的なものをおくために利用します。
type=tmpfs
で指定します。
docker run -itd --name tmpfs1 --mount type=tmpfs,destination=/app nginx
#7 Docker Compose#
Docker compose とは、複数のコンテナから成るサービスを構築・実行する手順を自動的にし、管理を容易にする機能です。
Docker compose では、compose ファイルを用意してコマンドを1 回実行することで、そのファイルから設定を読み込んですべてのコンテナサービスを起動することができます。
##7-1 docker-compose.yml##
サービス | 説明 |
---|---|
image | ベースイメージの指定 |
build | Dockerfileの指定 |
command | コンテナ内で実行するコマンドの設定 |
links | コンテナ間リンク設定 |
ports | ホストOS外部への公開ポート設定 |
expose | コンテナ間のみでの公開ポート設定 |
volumes | ボリュームマウントの設定 |
volumes_from | 別コンテナをボリュームとしてマウントするための設定 |
environment | 環境変数設定 |
env_file | 環境変数をファイル読み込みで設定 |
container_name | コンテナの名前設定 |
##7-2 docker-composeインストール##
OSごとのインストール方法は↓。
Install Docker Compose
インストールされていることを確認しておきましょう。
docker-compose --version
##7-3 docker-compose.ymlの作成##
作業ディレクトリdocker-compose-test
を作成しておきましょう。
mkdir docker-compose-test
cd docker-compose-test
ここでは、db
とwordpress
を作成しています。
version: '3'
services:
db:
image: mysql:5.7
volumes:
- "./.data/db:/var/lib/mysql"
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
links:
- db
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_PASSWORD: wordpress
後は以下コマンドで起動完了です。
docker-compose up -d
#8 dockerignore#
Dockerfileからイメージをビルドする場合、Dockerfileの存在するディレクトリの中身はtarで固められdaemonへと送られます。
このようなimageに含まないファイルも送信するため、dockerignoreを使います。
そもそも不要なファイルを含めなければいいと思いますが。。。
詳しくは、↓のページを参考にさせていただきました。
.dockerignore アンチパターン