Dockerの忘れそうなところをメモ。

Dockerコンテナの実行

docker run

pull, create, startを一気にやっちゃう

  • -v /User/takaaki/html:/usr/share/nginx/html:ro

バイトマウントする。roとかだとread onlyオプションをつけることができる。

  • -rm

コンテナを停止したときに削除する。

  • -d

バックグランド実行

  • -e AUTHOR="Takaaki"

環境変数を設定できる。

  • --link static-site:ss

リンク先に通信できるようになる。リンク先の環境変数を追加できる。

docker build

イメージを作成。引数にビルドコンテキストを指定。

ビルドコンテキスト...イメージが参照する範囲を指定する。ここで指定した範囲がDocker Hubにpushされるため小さい方がいい。Dockerfileがあるディレクトリの場所でもある。

docker create

イメージからコンテナを作成。

  • -i

コンテナの標準入力を取得して双方向に接続.

  • -t

コンテナ内にtty(eletypewriter)を割り当てる。

docker cp

文字通りコピー。ホストからコンテナ、コンテナからホストどちらにもできる。

docker add

これは文字通りではない。tarを自動で展開したりURLからダウンロードしたりする処理が走る。cpが推奨される。

docker pause, docker unpause
docker stop, docker start
docker inspect
docker rmi

イメージを削除。

docker rm

コンテナを削除。

docker attach

コンテナに接続される。exitで抜けるとstopされる。itで実行していたならばctrl + p, ctrl + qで抜けるとstopされない。

docker exec

コンテナ内でコマンドを実行。docker exec -it {image} /bin/bashとしてbashを実行するのによく使われ、exitで抜けてもstopされないため安全であり推奨される。

Docker-machine

docker コンテナを動かすためのホスト環境を構築するためのツール

docker-machine create --driver virtualbox default

default というホスト環境を作成

eval \$(docker-machine env default)

default というホスト環境で docker コンテナを動かす環境変数を設定

docker-machine stop, docker-machine start

ホスト名を省略すれば Active になっているホストになる

docker-machine ip
docker-machine rm default
eval \$(docker-machine env -u)

default というホスト環境で docker コンテナを動かす環境変数の設定を解除

docker-machine rm default

ホストを削除する

aws 上にホスト環境を作成

.aws/credential

キーをここに置いておく

[default]<
aws_access_key_id = xxxxx
aws_secret_access_key = xxxxx
docker-machine create --driver amazonec2 --amazonec2-open-port 8000 --amazonec2-region ap-northeast-1 aws-sandbox

aws 上にホスト環境を作成

gcp 上にホストを作成

export GOOGLE_APPLICATION_CREDENTIALS=/Users/takaaki/Downloads/docker-test-276107-ba32e65800d4.json

環境変数を設定

docker-machine create --driver google --google-project docker-test-276107 --google-zone asia-northeast1-a vm01

gcp は 8000 番ポートを使うのにファイヤウォールの設定が必要

Docker のネットワーク

docker network ls

現在存在するネットワークを表示

docker network inspect bridge
docker network create my_nw
docker network connect my_nw alpine1

リンクは推奨されておらずこちらが推奨される

docker run -itd --name alpine3 --network my_nw alpine /bin/sh
docker network disconnect bridge alpine2

none network

ループバックインタフェース以外にネットワークを持たない。接続するには全てのネットワークから切断しなければならない。

host network

docker host と同じネットワーク設定を持つ。docker host 上で nginx サーバーを起動すると, ポートを設定せずに docker host 上の nginx サーバーにアクセスすることができる。

Standalone Swarm のオーバーレイネットワーク

  • docker-machine create mh-keystore
  • eval $(docker-machine env mh-keystore)
  • docker run -d --name consul -p 8500:8500 -h consul consul agent -server -bootstrap -client 0.0.0.0
    • -bootstrap
    • consul サーバーのリーダーであることがわかる
    • -client 0.0.0.0
    • consul へのアクセスを受け付ける ip アドレス
  • docker-machine create --swarm --swarm-master --swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" --engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" --engine-opt="cluster-advertise=eth1:2376" mhs-demo0
  • docker-machine create --swarm --swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" --engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" --engine-opt="cluster-advertise=eth1:2376" mhs-demo1
  • eval $(docker-machine env --swarm mhs-demo0)
  • docker network create --driver overlay --subnet=10.0.9.0/24 mh-net
  • docker run -itd --name web --network mh-net --env "constraint:node==mhs-demo0" nginx
  • docker run -it --rm --network mh-net --env "constraint:node==mhs-demo1" busybox wget -O- http://web

コンテンツが取得できる

Docker のデータ管理

volume

ホスト側でファイルの編集をしない。同じホスト内のコンテナでのみ共有できる。docker の管理領域

docker volume create my-vol
docker volume ls
docker volume inspect my-vol
docker volume rm my-vol
docker run itd --name mount-c1 -v vol1:/app nginx:latest

新しいボリュームをマウントすると空のボリュームが作成される。

docker run -itd --name mount-c2 --mount source=vol1,target=/app nginx:latest

既存のボリュームをマウントすると普通にマウントされる。-v よりこちらのが推奨される

docker run -itd --name mount-c3 --mount source=copy-vol,destination=/etc/nginx nginx

コンテナ側に存在するディレクトリに新しいボリュームをマウントすると、コンテナ側のディレクトリにあったファイルがボリュームにマウントされる。

コンテナ側に存在するディレクトリに既存のボリュームをマウントすると普通にマウントされ, コンテナ側のディレクトリにあったファイルは隠れて見えない状態になる。

docker run -itd --name mount-c4 --mount source=copy-vol,destination=/etc/nginx,readonly nginx

読み取り専用としてマウントする

docker run -itd --name mount-c5 -v copy-vol:/etc/nginx:ro nginx

bind mount

ホスト側でファイルを編集することを念頭においている。任意のファイルやディレクトリをマウントできる。

docker run -itd --name bind-test1 -v "\$(pwd)"/source:/app nginx

存在しないディレクトリをマウントすれば, ホスト側にディレクトリが作成される。デフォルトで読み書き可能。

docker run -itd --name bind-test2 --mount type=bind,src="\$(pwd)"/source2,dst=/app nginx

存在しないディレクトリをマウントすれば, エラーになる。誤って空のディレクトリをマウントせずに済む

tmpfs

メモリ領域をマウントすることができる

--tmpfs

これはオプションを設定できないので非推奨

docker run -itd --name tmptest --mount type=tmpfs,destination=/app nginx
docker run -itd --name tmptest2 --mount type=tmpfs,destination=/app,tmpfs-size=5000000000,tmpfs-mode=700 nginx

Docker Compose

version: "3"
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {} # 定義しておく必要がある

Django

FROM python:3
ENV PYTHONUNBUFFEERED 1 # 標準出力やエラー出力をバッファにためない
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code
Django==2.0
psycopg2
version: "3"
services:
  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: pass
  web:
    build: .
    command: python3 manage.py runserver 0.0.0.0:8000 # コンテナ起動時のコマンド。コンテナ実行時にコマンドが渡された場合は上書きされる。
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db # webよりもdbを先に起動させる宣言

docker-compose run web django-admin.py startproject examplepj .

# settings.py

ALLOWED_HOSTS = ['localhost']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD': 'pass',
    }
}

docker-compose up -dをすれば Django が動いて, localhost:8000にアクセスできる

polls アプリケーションの作成

docker-compose run web python3 manage.py startapp polls

# polls/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
# polls/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index')
]
# examplepj/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls', include('polls.urls')),
    path('admin/', admin.site.urls),
]

localhost:8000/pollsにアクセスできるようになる

Ruby on Rails

FROM ruby:2.3.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
source 'https://rubygems.org'
gem 'rails', '5.0.0.1'

touch Gemfile.lock

version: "3"
services:
  db:
    image: postgres
    restart: always
    environment:
    POSTGRES_PASSWORD: pass
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

docker-compose run web rails new . --force --database=postgresql

# Use postgresql as the database for Active Record
gem 'pg', '~> 0.20.0' # pgのバージョンをあげる

docker-compose build

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: pass
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

docker-compose run web rake db:create

localhost:3000にアクセスすれば rails のデフォルトの画面にアクセスできる

scaffold

docker-compose run web bin/rails g scaffold User name:string

docker-compose run web bin/rake db:migrate

localhost:3000/usersにアクセスできるようになる

各種コマンド

version: "3"
services:
  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: pass
    volumes:
      pgdatavol: /var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  pgdatavol:
docker-compose down -v

yml で定義したコンテナやネットワークを削除。-v でボリュームも削除できる

docker-compose ps

yml で定義したコンテナの状態を見ることができる

docker-compose run web bin/rake db:create
docker-compose run web bin/rake db:migrate
docker-compose stop, start

docker swarm

swarmで使われるポート番号
  • クラスタ間通信: TCP 2377
  • ノード間通信: TCP/UDP 7946
  • オーバーレイネットワークトラフィック用: UDP 4789
docker swarm init --advertise-addr 192.168.99.100
docker node ls

managerでのみ実行可能

docker swarm join-token [manager, worker]

managerまたはworkerをクラスタに追加するコマンドを表示

docker swarm join --token SWMTKN-1-3w5rbtkswqrezih7guqylvxfn87jrsvd9rhm1xjyhebrqliza4-cpiscy3z0pm0m24w6yiv5grqi 192.168.99.100:2377

今いるホストをクラスタに追加する

docker run -d --name=viz --publish=808:8080/tcp --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock dockersamples/visualizer

visualizerというクラスタを監視するツール

docker service create -d --name nginx --replicas 3 --publish 8000:80 nginx
docker service update --publish-[add, rm] 8000:80 --detach=true web
docker service rollback --detach=true web

2回行うとrollbackがrollbackされる

docker service inspect [--pretty] web
docker service ps web
docker service rm web
docker service create --name nginx --constraint 'node.role==manager' --replicas 2 --detach=true nginx

managerホストに2つのタスクを作成する

docker service create --name host-nginx --publish mode=host,published=8000,target=80 --replicas 2 nginx

ホスト内にのみポートを公開して負荷分散しないようにする

docker service create --name web --mode=global nginx

1ホスト1タスクが作成される

managerの停止が許容される数

(N - 1) / 2、つまり半分以上のmanagerが動いていなければならない

docker node promote worker2

workerノードをmanagerノードに昇格させる

docker service update --force web

タスクの再配置が行われる

docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6

遅延の間隔を開けて順にupdateが行われる

docker service scale web=4

タスクの数を変更する

docker node update --availability drain manager1

メンテナンスを行うときにタスクを受け付けないようにする

docker-compose.yml

ワードプレスサービスを作成するときのymlの一例

version: '3.4'

services:
  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: samplewp
    deploy:
      replicas: 2
      placement:
        constraints:
          - node.role == worker
    depends_on:
      - mysql

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: samplewp
    volumes:
      - mysql_vol:/var/lib/mysql
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.hostname == manager1
volumes:
  mysql_vol:
docker stack deploy --compose-file docker-compose.yml wp
docker stack ls
docker stack rm