師匠「環境構築にはDockerを使いましょう」
ぼく「承知っす!!!(Docker...?)」
ってことでDockerについて調べてみました。
Dockerとは
参考
Docker入門(第一回)~Dockerとは何か、何が良いのか~
要約
-
Dockerは、コンテナ型の仮想環境を配布・実行するためのプラットフォーム。
-
仮想マシンとは違う。
- 仮想マシン
ホストマシン上でハイパーバイザを利用してゲストOSを動かす。そのうえでミドルウェアなどを動かす。 - Docker
ホストマシンのカーネルを利用して、プロセスやユーザを隔離する。従って軽量・高速。
- 仮想マシン
-
ミドルウェアのインストールや各種環境設定をコード化して管理する。
- コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
- 作成した環境を配布しやすい。
- スクラップ&ビルドが容易にできる。
-
Dockerイメージは、Web上のDocker Hubで公開されている。
Dockerイメージを取得すれば、すでに必要なミドルウェアなどがインストールされているDockerコンテナを起動できる。
感想
仮想マシンより軽快に動くらしい。確かに仮想マシンってもっさりしている印象あるよね。
「コード化して管理」ってなんか今風な感じ。
いまいちイメージわかないけど、とりあえず触ってみよう。
Dockerセットアップ、コンテナ起動
参考
Docker入門(第二回)~Dockerセットアップ、コンテナ起動~
Dockerのインストール
ハマった。
例はCentOSだけど、Linuxが好きなのでAmazon Linux2に入れようとした。
いくらやっても
sudo amazon-linux-extras install docker
これでこける。
失敗例
# sudo amazon-linux-extras install docker
Installing docker
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Cleaning repos: amzn2-core amzn2extra-docker docker-ce-stable
12 metadata files removed
6 sqlite files removed
0 metadata files removed
(略)
Resolving Dependencies
--> Running transaction check
---> Package docker.x86_64 0:18.09.9ce-2.amzn2 will be installed
--> Processing Dependency: runc = 1.0.0 for package: docker-18.09.9ce-2.amzn2.x86_64
--> Processing Dependency: containerd = 1.2.6 for package: docker-18.09.9ce-2.amzn2.x86_64
--> Processing Dependency: pigz for package: docker-18.09.9ce-2.amzn2.x86_64
--> Processing Dependency: libcgroup for package: docker-18.09.9ce-2.amzn2.x86_64
--> Running transaction check
---> Package containerd.io.x86_64 0:1.2.13-3.1.el7 will be installed
--> Processing Dependency: container-selinux >= 2:2.74 for package: containerd.io-1.2.13-3.1.el7.x86_64
---> Package libcgroup.x86_64 0:0.41-21.amzn2 will be installed
---> Package pigz.x86_64 0:2.3.4-1.amzn2.0.1 will be installed
--> Finished Dependency Resolution
Error: Package: containerd.io-1.2.13-3.1.el7.x86_64 (docker-ce-stable)
Requires: container-selinux >= 2:2.74
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
Installation failed. Check that you have permissions to install.
調べてみたら、こんな記事が。
そうかそうか、docker-ce.repoが邪魔だったのね。
なんでCentOSの記事をそのまま引用したんだろう、反省。
削除して、もう一回
sudo amazon-linux-extras install docker
でいけました。うんうん、知ってた知ってた。
Dockerを動かしてみる
準備
Dockerサービス起動
# systemctl start docker.service
サービスの起動確認
# systemctl status docker
Dockerの自動起動設定
# systemctl enable docker
試しにDockerコマンド実行
# docker info
この辺は特に問題なくいきました。
DockerイメージとDockerコンテナ
- まず、Dockerイメージがある。
- Dockerイメージをもとに、Dockerコンテナを起動する。
初期状態
イメージ一覧を表示
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
初期状態では、イメージはない。
従ってヘッダーのみが表示されている。
コンテナ一覧を表示
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナも起動していないため、ヘッダーのみが表示されている。
hello-worldイメージを使ってコンテナを動かす
イメージ取得→起動
# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752
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/
イメージ一覧を表示
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 14 months ago 1.84kB
イメージが追加されていることを確認。
コンテナ一覧を表示
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
24c4702a238c hello-world "/hello" About a minute ago Exited (0) About a minute ago laughing_pascal
コンテナも起動していることを確認。
「STAUS」が「Exited」になっているため、正確には停止している。
(hello-worldイメージは、MSGを出漁するだけなので停止で問題ない。)
イメージ、コンテナの削除
コンテナ削除
# docker rm <コンテナ名>
もしくは
# docker rm <CONTAINER ID>
イメージ一覧を表示
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 14 months ago 1.84kB
イメージは消えていない。
コンテナ一覧を表示
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナは消えている。
イメージ削除
# docker rmi <イメージ名>
もしくは
# docker rmi <IMAGE ID>
イメージ一覧を表示
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
イメージも消えた。
コンテナ一覧を表示
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
もちろん、コンテナは消えている。
Nginxイメージの使用
Nginxイメージの取得
# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
68ced04f60ab: Pull complete
c4039fd85dcc: Pull complete
c16ce02d3d61: Pull complete
Digest: ***
Status: Downloaded newer image for nginx:latest
Nginxコンテナの起動
# docker run -d --name nginx-container -p 8181:80 nginx
起動オプションは以下の通り。
オプション | 意味 |
---|---|
-d | バックグラウンド実行 |
--name <任意の名前> | コンテナ名を指定 |
-p <ホスト側のPORT>:<コンテナ側のPORT> | PORTを指定 |
http://<サーバのIP>:8181/
で、Nginxにアクセス可能。
(EC2の場合、セキュリティグループの設定変更が必要)
Dockerコマンドについて
参考
Docker入門(第三回)~各種dockerコマンドとDockerイメージ作成について~
Docker コマンドチートシート
各種コマンドによる操作
- Dockerイメージ取得、イメージ一覧確認
- コンテナ起動、コンテナ一覧確認
- コンテナへのログイン
- ファイルコピー(ホスト→コンテナ内)
- ファイルコピー(コンテナ内→ホスト)
- コンテナからDockerイメージ作成
- コンテナ起動、停止
- コンテナ削除
など。参考のリンク先をみれば良いので割愛。
ホスト側とのディレクトリ共有
起動時にvオプションをつけることで、ホスト側のディレクトリとコンテナ内のディレクトリを共有することが可能。
使用例としては、ログの出力先など。
例えばコンテナ内でログを出力していた場合、コンテナの停止とともに消えてしまうため。
オプション | 意味 |
---|---|
-v <ホスト側ディレクトリ>:<コンテナ側ディレクトリ> | 両ディレクトリを共有にする |
ディレクトリ共有した状態で起動
# docker run -it -d -p 18080:8080 -v /root/tomcat-container/logs:/share/logs --name tomcat centos:7
イメージの作成
ここまではイメージからコンテナを作ってきたが、コンテナからイメージを作ることもできる。
コンテナの停止(やらなくても作成できるみたい。停止したほうが安全?)
# docker stop nginx-container
nginx-containerコンテナから、nginx2イメージを作成
# docker commit nginx-container nginx_2
イメージを確認
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx_2 latest 4a4ce52ad449 6 seconds ago 127MB
nginx latest a1523e859360 6 days ago 127MB
nginx_2イメージが作成されている。
試しに作成したイメージからコンテナを起動してみる。
Nginx_2コンテナの起動
# docker run -d --name nginx2-container -p 8182:80 nginx_2
起動したコンテナの確認
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53e414bab96d nginx_2 "nginx -g 'daemon of…" 41 seconds ago Up 39 seconds 0.0.0.0:8182->80/tcp nginx2-container
4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 29 minutes 0.0.0.0:8181->80/tcp nginx-container
確認できたので止める
# docker stop nginx2-container
停止の確認
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53e414bab96d nginx_2 "nginx -g 'daemon of…" 2 minutes ago Exited (0) 9 seconds ago nginx2-container
4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 31 minutes 0.0.0.0:8181->80/tcp nginx-container
コンテナの削除
# docker rm nginx2-container
削除の確認
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 31 minutes 0.0.0.0:8181->80/tcp nginx-container
Dockefileについて
参考
Dockerfileって何?
公開されているDockerイメージに、「必要なパッケージやアプリを追加する」「各種設定をする」など少し手を加えておきたい場合に使用するもの。
Dockerfile内に、実行したい内容を記述する。
Dockerfileを使用してみる
…と思ったけど、参考記事の例はtomcatだしちょっと微妙かなと。
どうせならLaravel環境作成したりしたいなと。
そんなことを思ってたらこんなものがあった。
Dockerを使ってLaravel開発環境構築
最高っす。ドンピシャっす。
というわけで、実際に動かすのは別の機会にすることにした。
コンテナ間通信について
参考
コンテナ間通信
コンテナ同士の通信をするためには、以下2通りの方法がある。
- Dockerネットワークを作成し、コンテナ名で接続
- --link オプションを使用して起動する
Dockerネットワークの作成
例として、Dockerネットワーク(bridgeタイプ)を作成する。
その他のタイプについてはこちら参照とのこと。
「network1」というDockerネットワークを作成
# docker network create network1
Dockerネットワークの一覧を表示
# docker network ls
NETWORK ID NAME DRIVER SCOPE
064b0ea3a75c bridge bridge local
7281bec71e9e host host local
3585fc587596 network1 bridge local
272c5bc211eb none null local
「network1」が存在することが確認できる。
デフォルトで「bridge」も存在しているが、これはDNS設定がされておらず名前解決できないため、コンテナ名を使用したコンテナ間通信ができないらしい。
Dockerネットワークの詳細を表示
# docker network inspect network1
[
{
"Name": "network1",
"Id": "3585fc587596ba17195364d8aea2e77add0978813782bfb21b15486153df109c",
"Created": "2020-03-04T17:38:12.168101241Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
「network1」を使用したコンテナを作成
# docker run -d --name nginx3-container --network network1 -p 8183:80 nginx_2
起動したコンテナを確認
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20158137a4ce nginx_2 "nginx -g 'daemon of…" 3 seconds ago Up 1 second 0.0.0.0:8183->80/tcp nginx3-container
1487009fb41a nginx_2 "nginx -g 'daemon of…" 12 minutes ago Up 12 minutes 0.0.0.0:8182->80/tcp nginx2-container
4e29184909ff nginx "nginx -g 'daemon of…" 35 hours ago Up 6 hours 0.0.0.0:8181->80/tcp nginx-container
なおコンテナ間通信をする場合、PORT番号はコンテナ内部で使用しているPORTを指定すること。
例
MySQLのコンテナを以下のコマンドで作成した場合、ホスト側のPORTは19090、コンテナ内のPORTは9090となる。
# docker run --name mysql --network wordpress-network -p 19090:9090 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
この場合、コンテナ間通信で指定するPORTは「9090」となる。
--linkオプションによる通信
あらかじめ、mysqlコンテナを「some-mysql」という名前で作成
# docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
--linkオプションを用いて「some-mysql:mysql(wordpressコンテナ内で使用しているMySQLのホスト名)」を指定
# docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpress
Docker Composeについて
参考
Docker Composeとは
Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。
複数のコンテナを同時に起動したり、オプションを省略できるもの(?)
Docker Composeのインストール
Dockerがインストールされている環境で以下を実行
# curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
Docker Composeのインストールを確認
# docker-compose --version
docker-compose version 1.21.2, build a133471
docker-compose.ymlについて
Docker Composeを使用する場合、「docker-compose.yml」というファイルが必要となる。
このファイルには、以下のような情報を定義する。
- Dockerイメージをビルドするための情報(使用するDockerfile、イメージ名など)
- コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
- 使用するDockerネットワーク
mysqlとwordpressのコンテナを起動するrunコマンド
# docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
# docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpress
これを「docker-compose.yml」に記載すると、以下の通り。
version: '3'
services:
wordpress:
image: wordpress
container_name: some-wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_PASSWORD: my-secret-pw
mysql:
image: mysql:5.7
container_name: some-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
自分で作成した(公開でない)Dockerイメージを使用する場合(例)
version: '3'
services:
tomcat:
build: ./tomcat
image: tomcat-image
container_name: tomcat1
ports:
- 8081:8080
volumes:
- ./tomcat/share/logs:/share/logs
runコマンドのオプションと「docker-compose.yml」の記載内容を比較すると、以下の通り。
設定内容 | runコマンドのオプション | docker-compose.yml |
---|---|---|
コンテナ名 | --name | container_name |
環境変数 | -e | environment |
ポートフォワード | -p | ports |
使用するDockerイメージ | コマンドの最後 | image |
Dockerfileの指定 | docker buildコマンド | build |
共有ディレクトリ | -v | volumes: |
「--link」オプションに対応するものはないが、そもそも「docker-compose.yml」を使用した場合は自動でDockerネットワークを作成するため、自動でservice名で名前解決ができるようになっている。
「docker-compose.yml」を使用してコンテナを起動する。
# cd <docker-compose.ymlが置かれているディレクトリ>
docker-composeによる起動
# docker-compose up -d
起動の確認
# docker-commpose ps
Name Command State Ports
------------------------------------------------------------------------------
some-mysql docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
some-wordpress docker-entrypoint.sh apach ... Up 0.0.0.0:8080->80/tcp
次は、Laravel環境を構築をしてみる。