Skip to content

Instantly share code, notes, and snippets.

@wang-zhijun
Last active June 13, 2017 05:02
Show Gist options
  • Select an option

  • Save wang-zhijun/bafc887322cdaa52854f1eab7e096500 to your computer and use it in GitHub Desktop.

Select an option

Save wang-zhijun/bafc887322cdaa52854f1eab7e096500 to your computer and use it in GitHub Desktop.
docker

Docker SwarmでGo Appを動かすときログをファイルに吐き出しても、コンテナ内部のファイルに吐き出しているだけで、dockerのscratchイメージベースに作られているイメージはそもそもShellはない、ログをホストに出したいので、docker servce createコマンドに--mountオプションを使って、コンテナの中のファイルとホストのファイルを紐づくことができる。

結論からいうとしたのコマンドで

docker service create --replicas 2 --env ATHENA_ENV=dev --name athena -p 3000:3000 --mount type=bind,source=/var/log/athena/console.log,destination=/console.log  dg-general-use.objectstorage.cloud.egg.jp:5000/athena:1.2.3

事前にDocker Swarmの各ホストに/var/log/athena/console.logファイルを作成する必要がある。

これでコンテナはどのホストにスケジューリングされても大丈夫。

--mountオプションの文法

--mount type=bind,source=/file/in/host,destination=/file/in/container

イメージを変えずにAppをUpdateしたいときに--mount-addオプションを使うと強制的にアップデートができる

docker service update <app-name> --replicas 2 --mount-add type=bind,source=/var/log/athena/console.log,destination=/another/dir/console.log --image example.com:5000/athena:1.2.3

これでコンテナはローリングアップデートされる。

似ているようなオプションは--env, --env-add--env-rmもある。

上の例ではmountするタイプはbindになっているが、data volumeをbindする(type=volume,source=...,destination=...)こともできる


Docker Swarmの中にGo Appを動かすときにできるだけGo Appイメージのサイズを小さくしたい。

イメージをBuildするときにCentosを指定して、なんの不自由もなかったが、GoのBinaryを動かすだけで、Centos中の不要なファイルついてきて、コンテナの起動にオーバーヘッドをもたらすだけ。イメージを作成すると200Mを超えてしまう。

FROM centos:7

RUN mkdir /app
ADD athena /app

CMD ["./athena"]

なので、DockerのScratchイメージからBuildできるかを調べていた。athenaアプリの中にタイムゾーンを設定する必要があるため

  • zoneinfoファイルが必要

https関連の通信も発生する可能性が高いため、

  • Trust storeルート証明証関連のファイルも必要

結論からいうと、下のようなDockerfileになる。

FROM scratch

ADD config/ca-certificates.crt /etc/ssl/certs/
ADD config/zoneinfo.tar.gz /

ADD athena /
ADD config/app.toml /

WORKDIR /
CMD ["/athena"]

scratch自体のサイズは0 byte、shellもないので、コンテナ立ち上げても、docker exec -it <container-id> /bin/bashで入れない。

Trust Storeルート証明書ca-certificates.crtMozillaのデータをダウンロードする

curl -o ca-certificates.crt https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt

タイムゾーンの情報zoneinfo.tar.gzはCentos VMに入って、取ってくる

tar cfz zoneinfo.tar.gz /usr/share/zoneinfo

これらの情報は取得してきたらGoのAppをbuildするときに静的コンパイルが必要で、必要なファイルは全部バイナリに入れて、Gun Libraryを依存しないようにする。

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -ldflags '-s' -installsuffix cgo -o athena main.go

このコンパイルが終わると、動的実行ファイルでなければいい

$ ldd athena
        動的実行ファイルではありません

これで外部環境でコンパイルしたバイナリをイメージに入れてサイズを200Mから10Mに減らすことができる


MongoDBコンテナ

MongoDBのデータはData Volumeに保存する MongDBのインスタンスを起動するときにData VolumeをMountするようにする。 MongoDBがコンテナの/data/dbに保存されているデータは全部ローカルマシンの/mnt/general-use/docker-mongodb-dataに永久保存されます。他のディレクトリに保存されているデータはコンテナが削除されるとローカルマシンからも消える

$ docker create --name mongo-data --volumes /mnt/general-use/docker-mongodb-data:/data/db centos

$ docker run -d --volumes-from mongo-data --name mongo -p 27017:27017 mongo
8d2181dd25affd60e1596e8cccdf8031692a1d795ceffd644d32bad96dbe8666

Private Docker RegistryにBasic認証を適応

mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/htpasswd
docker run -d -p 5000:5000 --restart=always --name registry -v `pwd`/private-docker-registry/certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain.pem -e REGISTRY_HTTP_TLS_KEY=/certs/privkey.pem -v `pwd`/private-docker-registry/auth:/auth
-e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -v /mnt/general-use/private-docker-registry/data/:/var/lib/registry registry:2

Private Docker RegistryにPush

http://stackoverflow.com/questions/28349392/how-to-push-a-docker-image-to-a-private-repository

docker tag redis dg-general-use.objectstorage.cloud.egg.jp:5000/redis
docker push dg-general-use.objectstorage.cloud.egg.jp:5000/redis

サービスathenaをローリングアップデートして、新しいimage 1.1を使うように

$ docker service update athena --image wzj8698/athena:1.1

Run swarm join-token --rotate to invalidate the old token and generate a new token. Specify whether you want to rotate the token for worker or manager nodes:

docker swarm join-token  --rotate worker
docker swarm join-token  --rotate manager


Docker SwarmのTokenを調べる

docker swarm join-token --quiet worker
docker swarm join-token --quiet manager


docker-machine の各種コマンド実行時に TLS 接続エラーになったら

Unable to query docker version: Get https://192.168.99.102:2376/v1.15/version: x509: certificate is valid for 192.168.99.101, not 192.168.99.102
docker-machine regenerate-certs <hostname>

docker volume

docker volumeを作成して、 data というvolumeを利用しているコンテナは /tmpディレクトリへの書き込みだけは消えない

$ docker create --name data --volume /tmp ubuntu
$ docker run -it --name i1 --volumes-from data ubuntu /bin/bash
# echo "abc" > /tmp/aaa # 消えない
# echo "cde" > /home/bbb # 消える

Docker for mac

wget https://download.docker.com/mac/stable/Docker.dmg
wget https://github.com/docker/toolbox/releases/download/v1.12.0/DockerToolbox-1.12.0.pkg

docker-machineをインストール

$ wget https://github.com/docker/machine/releases/download/v0.7.0/docker-machine-`uname -s`-`uname -m` 
$ sudo mv docker-machine-`uname -s`-`uname -m` /usr/local/bin/docker-machine 
$ sudo chmod +x /usr/local/bin/docker-machine

dockerをインストール

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum makecache fast
sudo yum list docker-ce.x86_64  --showduplicates |sort -r
sudo yum install docker-ce

add user to group

現在のユーザーが普通権限でdockerを操作できるように

sudo groupadd docker
sudo gpasswd -a ${USER} docker

docker exec

Runningになっているコンテナーにはいる

docker exec -it d387fb450fc5 bash

docker run

$ docker run -d -P --name static-site prakhar1989/static-site
d3157304e269975ba5d7bf6a8024db4d13366e0c5d1d5157f644354b7d23c212

-d will detach our terminal,

-P will publish all exposed ports to random ports and finally

--name corresponds to a name we want to give.

Centosでdocker runを実行する時に下のエラーをでることがあります

Usage of loopback devices is strongly discouraged for production use. 
Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.

この場合は/etc/sysconfig/docker-storageを下のように修正、dockerを再起動sudo systemctl restart docker.service

DOCKER_STORAGE_OPTIONS="--storage-opt dm.no_warn_on_loop_devices=true"

実際にこのエラーを抑制しないほうがいいので、ここを参照

http://stackoverflow.com/questions/31620825/warning-of-usage-of-loopback-devices-is-strongly-discouraged-for-production-use

立ち上がったコンテナのportをチェックする

$ docker port static-site
443/tcp -> 0.0.0.0:32768
80/tcp -> 0.0.0.0:32769

$ curl http://localhost:32769/

ローカルホストの8888番ポートにアクセスするとdocker container の80番ポートにリクエストが行く, containerの名前はweb_test

docker run -d --name web_test -p 8888:80 docker.io/nginx

The bridge network is the network in which containers are run by default.

$ docker network ls
NETWORK ID          NAME                DRIVER
3333d28c4c2c        bridge              bridge
a44766c8c8dc        host                host
06a72a5cb34c        none                null

172.17.0.3 and 172.17.0.2is the IP address this container has been allotted.

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "3333d28c4c2c76b490ded17e9c281b9b76f5026824fccb681ab5a26f90f737cc",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
 ...

docker run--rmオプションをつけるという意味はcontainerがexitすると、container自体はclean upされる。

docker ps -aで確認することができる。一回だけのコマンドを打つときに便利。

docker run -it --rm hello-world

docker attach

すでに起動されているDocker Containerにアタッチして、入ることができる

$ docker run -it --name tmp_elixir elixir /bin/bash
root@58836313c3a0:/# exit
$ docker start tmp_elixir
$ docker attach tmp_elixir

ElixirをインストールするDockerfile

FROM centos:7

RUN yum -y update && yum clean all

# OSを日本語にする
RUN yum reinstall -y glibc-common && yum clean all
ENV PATH /usr/local/elixir/bin:$PATH
ENV LANG jp_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

RUN yum install -y wget unzip epel-release

# Install Erlang
RUN wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
RUN rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
RUN yum install -y erlang

# Install Elixir
RUN wget https://github.com/elixir-lang/elixir/releases/download/v1.2.5/Precompiled.zip
RUN mkdir -p /usr/local/elixir
RUN cd /usr/local/elixir && unzip /Precompiled.zip

# Install hex & rebar
RUN mix local.hex <<< 'Y'
RUN mix local.rebar <<< 'Y'

Dockerfileをbuild

docker build -t wzj8698/elixir:latest .

docker imagesのヘルプを

docker help images

--link

同一ホスト上のコンテナ間で通信する際に、接続したい相手のネットワーク情報(IPアドレスなど)を取得する仕組み。次の2つの形で情報を取得できる。

  • 環境変数
  • /etc/hosts ファイル
docker run -d -p 80:80 -p 11111:22222 --name Container1 centos ping localhost

次に、接続元のコンテナを --link オプションを使って起動する。--link は、<接続先コンテナ名:エイリアス名>という形式で指定する。

docker run -it --name Container2 --link Container1:c1 centos /bin/bash

接続元コンテナ内から環境変数を表示すると、エイリアス名のついた環境変数が作られて、接続先の情報が入っていることが分かる。

[root@2c578037be18 /]# env | grep C1 | sort
C1_NAME=/Container2/c1
C1_PORT=tcp://172.17.0.2:80
C1_PORT_22222_TCP=tcp://172.17.0.2:22222
C1_PORT_22222_TCP_ADDR=172.17.0.2
C1_PORT_22222_TCP_PORT=22222
C1_PORT_22222_TCP_PROTO=tcp
C1_PORT_80_TCP=tcp://172.17.0.2:80
C1_PORT_80_TCP_ADDR=172.17.0.2
C1_PORT_80_TCP_PORT=80
C1_PORT_80_TCP_PROTO=tcp

また、/etc/hosts に接続先のエントリが追加される。

[root@2c578037be18 /]# cat /etc/hosts
...
172.17.0.2      c1 c4adca15a85d Container1
172.17.0.3      2c578037be18

もう一つredisを使った例でredisイメージを使ったclient1とclient2がredis1サーバーに繋がる.client1から定義した変数myvarがclient2で取得する

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
855611bf2296        redis               "docker-entrypoint.sh"   48 seconds ago      Up 47 seconds       6379/tcp                      client2
eea6e2df7309        redis               "docker-entrypoint.sh"   2 minutes ago       Up 2 minutes        6379/tcp                      client1
ba13188b1ec1        redis               "docker-entrypoint.sh"   8 minutes ago       Up 8 minutes        6379/tcp                      redis1
docker pull redis
docker run -d --name redis1 redis # redisサーバー
docker run -it --link redis1:redis-server --name client1 redis sh # client1

# redis-cli -h redis-server
redis-server:6379> PING
PONG
redis-server:6379> set myvar DOCKER
OK
redis-server:6379> get myvar
"DOCKER"


docker run -it --link redis1:redis-server --name client2 redis sh # client2
# redis-cli -h redis-server
redis-server:6379> get myvar
"DOCKER"

docker create

docker createコマンドはコンテナーをつくるけど、起動しない

$ docker create --cidfile /tmp/web.cid nginx
6c463befb325be315a831f9047684a188fff787bada2064cd5af2da5a91d3e0b

$ cat /tmp/web.cid
6c463befb325be315a831f9047684a188fff787bada2064cd5af2da5a91d3e0b

$ docker ps --latest --quiet # 最後に起動したコンテナのidだけを表示
6c463befb325

$ docker ps --latest --quiet --no-trunc
6c463befb325be315a831f9047684a188fff787bada2064cd5af2da5a91d3e0b

inspectでみてみると起動していないことが分かる

$ docker inspect --format "{{.State.Running}}" 6c463befb325be315a831f9047684a188fff787bada2064cd5af2da5a91d3e0b
false

startさせる

$ docker start   6c463befb325be315a831f9047684a188fff787bada2064cd5af2da5a91d3e0b

--rm

if you’re experimenting with short-lived containers, you can avoid the cleanup burden by specifying --rm on the command. Doing so will automatically remove the container as soon as it enters the exited state.

$ docker run --rm --name auto-exit-test busybox:latest echo Hello World
Hello World

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

docker rm -v

-v, --volumes Remove the volumes associated with the container

$ docker rm -vf cass1

docker run -v

This command mounts the host directory, /src/webapp, into the container at /opt/webapp. If the path /opt/webapp already exists inside the container’s image, the /src/webapp mount overlays but does not remove the pre-existing content. Once the mount is removed, the content is accessible again.

$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

docker ps -a --filter

コンテナの終了コード(exit)と(status)にたいしてフィルタ可能、statusはrunning, exited, paused, created

$ docker ps -a --filter "status=exited"
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
ee0dbdb52fe7        cassandra:2.2       "/docker-entrypoint.s"   24 hours ago        Exited (143) 24 hours ago                       cass1
0b6c442d891a        alpine              "echo Data Container"    24 hours ago        Exited (0) 24 hours ago                         cass-shared

$ docker ps -a --filter "status=running"
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS                    NAMES
0a251dcf7f57        object-storage/mysql   "/sbin/init"        6 hours ago         Up 6 hours          0.0.0.0:3306->3306/tcp   mysql-object-storage

$ docker ps -a --filter "exited=143"
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
ee0dbdb52fe7        cassandra:2.2       "/docker-entrypoint.s"   24 hours ago        Exited (143) 24 hours ago                       cass1

docker inspect --format

jsonの形でコンテナの情報を出力

$ docker inspect --format='{{json .State}}' mysql-object-storage
{"Status":"running","Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":3771,"ExitCode":0,"Error":"","StartedAt":"2016-06-10T00:27:41.55468633Z","FinishedAt":"0001-01-01T00:00:00Z"}

docker commit

動いているコンテナにたいして変更をした後にコミットすることができる

$ docker commit mysql-object-storage mysql-test:1.0
sha256:02a957b83f21d3fa853d511f0a6ca0db40ed676232a956925752f8a82ae5ee36

docker rename

docker ps -aの結果の中のコンテナんの名前をかえる

$ docker rename condescending_roentgen new_name

docker run --hostname

コンテナにhostnameをつけて実行する

$ docker run --rm --hostname barker alpine:latest nslookup barker

Name:      wow
Address 1: 172.17.0.3 wow
nslookup: can't resolve '(null)': Name does not resolve

docker run --dns

コンテナに使われるDNSサーバーを指定する

$ docker run --rm --dns 8.8.8.8 --name dns_test -it busybox
/ # nslookup google.com
Server:    8.8.8.8
Address 1: 8.8.8.8 google-public-dns-a.google.com

Name:      google.com
Address 1: 2404:6800:4004:814::200e nrt13s37-in-x0e.1e100.net
Address 2: 216.58.220.238 nrt13s37-in-f14.1e100.net

docker diff

$ docker run -it --name image-dev ubuntu:latest /bin/bash
# apt-get update
# apt-get install git -y
# exit

image-devへの変化を見てみると

$ docker diff image-dev
C /var/log/alternatives.log
C /var/log/apt
C /var/log/apt/history.log
A /var/log/apt/term.log
C /var/log/dpkg.log

もう一例

$ docker run --name tweak-d busybox:latest rm /bin/vi
$ docker diff tweak-d
C /bin
D /bin/vi

docker volume

ローカルホストの~/docker-nginx/htmlディレクトリにウェブページを用意して、立ち上がったnginxがコンテナがそれを使うように

$ docker run --name nginx-blog -p 80:80 -d -v ~/docker-nginx/html/blog/_site:/usr/share/nginx/html nginx

docker tag

既存のイメージ ubuntu-gitを新しいタグをつける

$ docker tag ubuntu-git wzj8698/git:version1.0

$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
ubuntu-git            latest              1df63ab69570        2 days ago          254.1 MB
wzj8698/git           version1.0          1df63ab69570        2 days ago          254.1 MB

$ docker rmi 1df63ab69570
Error response from daemon: conflict: unable to delete 1df63ab69570 (must be forced) - image is referenced in one or more repositories

docker commit

イメージimage-devから新しいイメージをコミットする

docker run -it --name image-dev ubuntu:latest /bin/bash
...
docker commit -a "@name-of-the-author" -m "Commit message" image-dev ubuntu-git

Install Docker compose

# curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose


docker compose一例

docker-compose.ymlファイルを作成した後にdocker-compose up -dを実行する。-dオプションはdaemonとして実行するという意味。 http://localhost:8080/にアクセスするとwordpressが表示される。

web:
  image: wordpress
  links:
    - mysql
  environment:
    - WORDPRESS_DB_PASSWORD=sample
  ports:
    - "127.0.0.1:8080:80"

mysql:
  image: mysql:latest
  environment:
    - MYSQL_ROOT_PASSWORD=sample
    - MYSQL_DATABASE=wordpress

コンテナをチェックしてみる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
21d845162235        wordpress           "/entrypoint.sh apach"   5 minutes ago       Up 12 seconds       127.0.0.1:8080->80/tcp   wordpress_web_1
f3d5607883bf        mysql:latest        "docker-entrypoint.sh"   8 minutes ago       Up 13 seconds       3306/tcp                 wordpress_mysql_1

docker-machineでバーチャルホストを作成

$ docker-machine create --driver virtualbox host1
Creating CA: /Users/a21032773/.docker/machine/certs/ca.pem
Creating client certificate: /Users/a21032773/.docker/machine/certs/cert.pem
Running pre-create checks...
(host1) Image cache directory does not exist, creating it at /Users/a21032773/.docker/machine/cache...
...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env host1

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
host1   -        virtualbox   Running   tcp://192.168.99.100:2376           v1.11.2

machine1をactiveにする

$ eval "$(docker-machine env machine1)"

docker export/import

動いているあるいは停止しているコンテナをtarファイルにexportして、さらにできたtarファイルをimportすると、新しいimageができる

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
d387fb450fc5        nginx               "nginx -g 'daemon off"   3 weeks ago         Up 8 days           0.0.0.0:80->80/tcp, 443/tcp   nginx-blog
$ docker export d387fb450fc5 > docker_image.tar

$ cat docker_image.tar | docker import - another_image
sha256:f8d9f47f26543bea97217ae0ff8b98af9d5731bc151eb95abc386910b0d78557

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
another_image       latest              f8d9f47f2654        12 seconds ago      181.2 MB

外からMysqlコンテナにSQLファイルをRestore。-iオプションだけを使えばいい。

$ docker exec -i db mysql -uroot -pexample wordpress < dump.sql

docker swarm

swarmイメージをpullしてくる。 $ docker run swarm --help


docker-compose extends

When defining any service in docker-compose.yml, you can declare that you are extending another service like this:

web:
  extends:
    file: common-services.yml
    service: webapp

This instructs Compose to re-use the configuration for the webapp service defined in the common-services.yml file. Suppose that common-services.yml looks like this:

webapp:
  build: .
  ports:
    - "8000:8000"
  volumes:
    - "/data"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment