docker
Docker introduction
どっかーがんばるぞ~
docker vs. vagrant
同じ時期に Vagrant も見ていたので、やるならどっちかなぁと考えた時があったので。 ここ が優しい
docker installation
公式をごらんなさい。至って簡単です。 一応、mac用の簡単インストール: Qiita - Docker for Macをインストールしてみた
proxy の設定
これでだいたいカバーできそう: 防火壁の中の Docker でもプロキシ配下の環境ってのはいろいろ手間だし嫌だよね。
docker-compose
- 複数のコンテナの設定、起動をまとめて行うもの。
- installation: 公式をごらんなさい
TIPS
tips 書くよ。
イメージの操作
イメージ一覧(ダウンロード済のもの):
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> f99cd0762d12 3 days ago 248MB <none> <none> 6ebf2fc54f77 4 days ago 225MB <none> <none> 94b927c827e9 4 days ago 511MB <none> <none> 5c6e9b479563 4 days ago 531MB <none> <none> 03811835d1a3 4 days ago 531MB <none> <none> 9d49d5dccac0 4 days ago 531MB <none> <none> d8b062142c51 4 days ago 488MB centos 7 1e1148e4cc2c 2 months ago 202MB
イメージ削除:
docker rmi <image_id>
イメージの取得:
docker pull
- 解説: dockerhub などにある既成のコンテナイメージを取得するにはこれ
イメージのビルド:
docker build -t <name> <build_context>
- 解説: 自前のコンテナイメージを生成するにはこれ
- options:
-t <name>
: ここで指定した image name になる。<build_context>
: docker daemon に送信するディレクトリ。だいたい Dockerfile を編集しながら実行するので、カレンドディレクトリ.
を指定することが多い。大きいサイズの不要なファイルを底に置くのは避けよう(不必要にdocker daemonに送信されてビルドが長時間化する)--no-cache
をつけると作成済みレイヤーをキャッシュせず、1からビルドし直してくれる。
- その他説明:
- Dockerfile の各行がステップで、イメージのレイヤーになる。
コンテナ起動:
docker run <image_name> [<cmd_inside_container>]
- 解説: docker pull や docker build で取得or生成したイメージを元にコンテナを起動する。使い方によってはイメージ取得 (docker pull) も包含される
- 実行例 (詳細のコマンド解説は「コンテナの操作」の章で)
$ docker run docker/whalesay cowsay Hello! ________ < Hello! > -------- \ \ \ ## . ## ## ## == ## ## ## ## === /""""""""""""""""___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\______/
イメージの詳細情報を見る: docker inspect <image_name>
$ docker inspect my_whalesay [ { "Id": "sha256:6b362a9f73eb8c33b48c95f4fcce1b6637fc25646728cf7fb0679b2da273c3f4", "RepoTags": [ "docker/whalesay:latest", "my_whalesay:latest" ], "RepoDigests": [ "docker/whalesay@sha256:178598e51a26abbc958b8a2e48825c90bc22e641de3d31e18aaf55f3258ba93b" ], "Parent": "", "Comment": "", ...
Docker hub へログイン:
docker login [<url>]
イメージにタグ付け:
docker tag <image_name> <Docker ID>/<image_name>:<tag>
イメージをDocker hubへプッシュする:
docker push <Docker ID>/<image_name>:<tag>
- 事前にログインが必要 (
docker login
)
- 事前にログインが必要 (
起動中のコンテナからイメージとして保存する:
docker commit <container_name or container_id> <image_name>:<tag>
- 実行中のコンテナに入って色々編集したものを、イメージとして保存できる。
- ただし、 docker history に残らないので、何をしてあるのかがわからず、不自由する面も。
- ベーシックな使い方であれば、やはり Dockerfile を編集してイメージを作成するほうが良い。
履歴とレイヤーを確認する:
docker history <image_name or image_id>
$ docker history commit-test:ver2 IMAGE CREATED CREATED BY SIZE COMMENT 44ce43b51809 About a minute ago /bin/bash 10.5MB 47b19964fb50 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 3 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 3 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 3 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 3 weeks ago /bin/sh -c #(nop) ADD file:529264c6593975a61… 88.1MB
- commit で行われた変更は /bin/bash としか表現されていないため、このように何が行われたかわからなくなってしまう。
- 上の行ほど新しい更新=新しいレイヤー
コンテナの操作
コンテナを立ち上げるコマンド:
docker run --name <container_name> -d -p <host_port>:<container_port> <image_name>
- options:
-d
: toggle detach mode--rm
: Automatically remove the container when it exits- バインドマウント:
-v <host_dir>:<container_target_mount_point>:<readwrite_option>
<readwrite_option>
:ro
(readonly) だけ覚えておけば普通は良さそう- マウントされたファイルを編集すると、即時反映される(i.e. nginx の index.html を編集してブラウザをリロードすると更新後のファイルが見える)
- options:
起動中のコンテナを一覧:
docker ps
停止中のものを含む全てのコンテナを一覧:
docker ps -a
コンテナをストップ:
docker stop <container_name>
コンテナを削除:
docker rm test-nginx
コンテナを立ち上げ直す場合: ストップ、削除してから
docker run ...
し直すこと。ホストマシンのファイル → コンテナ内へのコピー:
docker cp <src_host_file_path> <container_name or container_id>:<target_path>
コンテナ内のファイル → ホストマシンへのコピー:
docker cp <container_name or container_id>:<src_path> <target_host_file_path>
コンテナのシェルに接続する方法2つ
docker attach <container_name or container_id>
: 抜ける時に誤ってコンテナを停止する事もできてしまうので非推奨かなdocker exec -it <container_name or container_id> /bin/bash
Automated Build
github への push をトリガーに、自動ビルドできる!
- dockerhubにリポジトリを作る
- githubにもリポジトリを作る
- dockerhubで automated build の設定をし、 github とリンクさせる
- 条件の設定は色々。ブランチへのコミットやタグ名を正規表現で引っ掛けてビルドのトリガーにできる。
- 以下はイメージ:
network
ネットワーク一覧の出力:
docker network ls
- 例:
NETWORK ID NAME DRIVER SCOPE 250df2d30d1f bridge bridge local 0fdcb5eceb66 gitbook-uml_default bridge local 081080240b02 host host local 1122ef3cedc6 nginx-proxy_default bridge local c8eb35a84aea none null local ba5737f49d7d revealjs-docker_default bridge local
- 補足
- 何も指定がないと、コンテナは デフォルトで用意される bridge というネットワークに接続される。
- 例:
ネットワークの詳細を見る:
docker network inspect <bridge_nw_name>
[ { "Name": "bridge", "Id": "250df2d30d1f1402be767281024f322cc261f4e8cb7d70e50d6803cb319135f3", "Created": "2019-02-25T12:34:44.2070634Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
ネットワークにコンテナが所属していると、以下のようなプロパティが追加されている:
"Containers": { "e331635c1597ed0b24b7547a4539d52cdb3c24bcc4504cbc3b01edd53489d98a": { "Name": "alpine1", "EndpointID": "260af34175578e7a81dc8c79e61a8733677d477493bf9bc563ad2b2b59f62b4e", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } },
コンテナ間の通信
- デフォルトの bridge では ip addr でしか通信できない
- 個別に作ったブリッジネットワークでは名前解決が可能
ブリッジネットワークの作成:
docker network create <nw_name>
特定のブリッジネットワークに稼働中のコンテナを接続する:
docker network connect <nw_name> <container_name>
コンテナ起動時に接続するブリッジネットワークを指定する:
docker run -itd --name alpine3 --network my_nw alpine
(alpine3 というコンテナを my_nw というネットワークに接続する)特定のブリッジネットワークにコンテナを切断する:
docker network disconnect <nw_name> <container_name>
作成したブリッジネットワークでは、名前解決が可能
- 証拠:
$ docker exec -it alpine2 /bin/sh / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:12 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:968 (968.0 B) TX bytes:0 (0.0 B) / # ping alpine1 PING alpine1 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.149 ms ^C --- alpine1 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.149/0.149/0.149 ms / # netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1 / # nslookup alpine1 Name: alpine1 Address 1: 172.18.0.2 alpine1.my_nw
- 証拠:
その他のデフォルトのネットワーク: none と host があるが、気が向いたら書く
- none network: どのネットワークにも接続しないようにすることができる
- host network: ホストと同じネットワークに所属する。 ポートのバインドをすることなく、ローカルホストから接続できる
お試し
試行中のメモなので正しくないかもですよ
公式の nginx でリバースプロキシ
- docker-compose+nginxでリバースプロキシを設定する
default.conf
のコピーは./nginx/Dockerfile
に書かずにdocker-compose.yml
のservices.nginx.volumes
に書いたら動いたよdocker-compose.yml
version: "3" services: nginx: image: nginx container_name: nginx ports: - "80:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - portainer - gitbook - swagger-ui restart: always gitbook: image: fellah/gitbook container_name: gitbook ports: - "4000:4000" volumes: - ./gitbook/data:/srv/gitbook restart: always swagger-ui: image: swaggerapi/swagger-ui container_name: swagger-ui volumes: - ./swagger-ui/data/swagger.yaml:/usr/share/nginx/html/swagger.yaml environment: API_URL: swagger.yaml ports: - "8080:8080"
nginx/default.conf
server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } location /portainer/ { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://portainer:9001/; } location /portainer/api/websocket/ { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_http_version 1.1; proxy_pass http://portainer:9001/api/websocket/; } # location /gitbook/ { # proxy_pass http://gitbook:4000/; # } location /swagger-ui/ { proxy_pass http://swagger-ui:8080/; } location /gitbookuml/ { proxy_pass http://gitbookuml:4000/; } }
swaggerapi/swagger-ui
jwilder/nginx-proxy で自動のリバースプロキシ
公式 nginx に比べてコンテナ追加・削除に自動追随できるっぽいです。できてます。
うまく行っていないやつ
消すか動くように直します。
gitbook
fellah/gitbook
- リンクの参照がどんどん崩れていく… 階層構造をやめるか、 network を分断するか, リンクの貼り方を相対じゃなく絶対にするか, gitbook のコードを monkey patchするか
newgyu/gitbookuml
- リンクの参照がどんどん崩れていく… 状況は同じ
- docker-compose.yml にはこれ足した
services: gitbookuml: image: newgyu/gitbookuml container_name: gitbookuml command: serve ports: - "4000:4000" volumes: - ./gitbookuml/data:/tmp/src restart: always
複数のWebアプリを1サーバーのDockerを使ってSSL対応のサブドメインで簡単に運用する
docker-compose up -d
したとき、php
のサービスに対して以下のエラーが出て進まない。debconf: delaying package configuration, since apt-utils is not installed ---(略)--- error: /usr/src/php/ext/mcrypt does not exist usage: /usr/local/bin/docker-php-ext-install [-jN] ext-name [ext-name ...] ie: /usr/local/bin/docker-php-ext-install gd mysqli /usr/local/bin/docker-php-ext-install pdo pdo_mysql /usr/local/bin/docker-php-ext-install -j5 gd mbstring mysqli pdo pdo_mysql shmop if custom ./configure arguments are necessary, see docker-php-ext-configure Possible values for ext-name: bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip Some of the above modules are already compiled into PHP; please check the output of "php -i" to see which modules are already loaded. ERROR: Service 'php' failed to build: The command '/bin/sh -c apt-get update && apt-get install -y libicu-dev libmcrypt-dev libxml2-dev && docker-php-ext-install -j$(nproc) intl mcrypt xml mbstring opcache && mkdir -p /var/www' returned a non-zero code: 1
かいてる通りやってもダメそうなので、勉強しないとなぁ…