end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

Docker Swarmは学びません

Docker/Kubernetes 実践コンテナ開発入門 (以下のurl)の 「4. Swarmによる実践的なアプリケーアプリケーション構築」を 写経しようとしましたが、

$ docker container exec -it manager \
    docker stack deploy -c ./stack/todo-mysql.yml todo_mysql

の実行でエラー。

コンテナオーケストレーションツールとしては、Docker Swarmよりも Kubernetes が、世の中的には、標準かと思いますので、 このentryの下部に様々記載してますが、Docker Swarmは学びません。

www.amazon.co.jp

目次

git clone https://github.com/gihyodocker/tododb

全体構成

┌stack(frontend) ──────────────────┐
│┌service(frontend_nginx) ────────────┐│
││┌──────────────────────┐││
│││container x3                                │││
│└┴──────────┰───────────┴┘│
│                       ┃HTTP(Proxy)               │
│┌service(frontend_web) ╂────────────┐│
││┌──────────┸───────────┐││
│││container x3                                │││
└┴┴──────────┰───────────┴┴┘
                          ┃HTTP
┌stack(app)───────╂─────────────┐
│┌service(app_nginx)──╂────────────┐│
││┌──────────┸───────────┐││
│││container x3                                │││
│└┴──────────┰───────────┴┘│
│                       ┃HTTP(Proxy)               │
│┌service(app_api)───╂────────────┐│
││┌──────────┸───────────┐││
│││container x3                                │││
└┴┴────┰───────────┰─────┴┴┘
              ┃write                 ┃read
┌stack(mysql)╂───────────╂───────┐
│┌─────╂───┐        ┌──╂──────┐│
││┌────┸───┤replica ├──┸─────┐││      
│││container x1    ┝━━━━┥container x3    │││
││└────────┤        ├────────┘││
│ service(mysql_master)         service(mysql_slave) │
└──────────────────────────┘

ノードの確認 (master x1 , worker x3)

$ docker container exec -it manager docker node ls
    HOSTNAME       STATUS   MANAGER STATUS   ENGINE VERSION
*   98e4c5b93225   Ready    Leader           20.10.23
    120608a59677   Ready                     20.10.23
    d4dc2bd958ec   Ready                     20.10.23
    e54446b93f5e   Ready                     20.10.23

todoappという名の overlayネットワーク作成

$ docker container exec -it manager \
    docker network create --driver=overlay --attachable todoapp

$ vi tododb/etc/mysql/mysql.conf.d/mysqld.cnf

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
datadir     = /var/lib/mysql
#log-error  = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address   = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
relay-log=mysqld-relay-bin 
relay-log-index=mysqld-relay-bin 

log-bin=/var/log/mysql/mysql-bin.log

$ vi tododb/add-server-id.sh

先程の mysqld.cnf に server-id を追記する為のものです

#!/bin/bash -e
OCTETS=(`hostname -i | tr -s '.' ' '`)

MYSQL_SERVER_ID=`expr ${OCTETS[2]} \* 256 + ${OCTETS[3]}`
echo "server-id=$MYSQL_SERVER_ID" >> /etc/mysql/mysql.conf.d/mysqld.cnf

$ vi tododb/prepare.sh

Master/Slave間のレプリケーション設定用

#!/bin/bash -e

# (1) MasterとSlaveを環境変数で制御する
if [ ! -z "$MYSQL_MASTER" ]; then
  echo "this container is master"
  exit 0
fi

echo "prepare as slave"

# (2) SlaveからMasterへの疎通確認をする
if [ -z "$MYSQL_MASTER_HOST" ]; then
  echo "mysql_master_host is not specified" 1>&2
  exit 1
fi

while :
do
  if mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "quit" > /dev/null 2>&1 ; then
    echo "MySQL master is ready!"
    break
  else
    echo "MySQL master is not ready"
  fi
  sleep 3
done

# (3) Masterにレプリケーション用のユーザーと権限の作成
IP=`hostname -i`
IFS='.'
set -- $IP
SOURCE_IP="$1.$2.%.%"
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD \
  -e "CREATE USER IF NOT EXISTS '$MYSQL_REPL_USER'@'$SOURCE_IP' IDENTIFIED BY '$MYSQL_REPL_PASSWORD';"
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD \
  -e "GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPL_USER'@'$SOURCE_IP';"

# (4) Masterのbinlogのポジションを取得
MASTER_STATUS_FILE=/tmp/master-status
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD \
  -e "SHOW MASTER STATUS\G" > $MASTER_STATUS_FILE
BINLOG_FILE=`cat $MASTER_STATUS_FILE | grep File | xargs | cut -d' ' -f2`
BINLOG_POSITION=`cat $MASTER_STATUS_FILE | grep Position | xargs | cut -d' ' -f2`
echo "BINLOG_FILE=$BINLOG_FILE"
echo "BINLOG_POSITION=$BINLOG_POSITION"

# (5) レプリケーションを開始する 
mysql -u root -p$MYSQL_ROOT_PASSWORD \
  -e "CHANGE MASTER TO MASTER_HOST='$MYSQL_MASTER_HOST', MASTER_USER='$MYSQL_REPL_USER', MASTER_PASSWORD='$MYSQL_REPL_PASSWORD', MASTER_LOG_FILE='$BINLOG_FILE', MASTER_LOG_POS=$BINLOG_POSITION;"
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "START SLAVE;"

echo "slave started"

$ vi tododb/Dockerfile

FROM mysql:5.7

# (1) パッケージアップデートとwgetインストール
RUN apt-get update
RUN apt-get install -y wget

# (2) entrykitのインストール
RUN wget https://github.com/progrium/entrykit/releases/download/v0.4.0/entrykit_0.4.0_linux_x86_64.tgz
RUN tar -xvzf entrykit_0.4.0_linux_x86_64.tgz
RUN rm entrykit_0.4.0_linux_x86_64.tgz
RUN mv entrykit /usr/local/bin/
RUN entrykit --symlink

# (3) スクリプトと各種設定ファイルのコピー
COPY add-server-id.sh /usr/local/bin/
COPY etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/mysql.conf.d/
COPY etc/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/
COPY prepare.sh /docker-entrypoint-initdb.d
COPY init-data.sh /usr/local/bin/
COPY sql /sql

# (4) スクリプトとmysqldの実行
ENTRYPOINT [ \
  "prehook", \
    "add-server-id.sh", \
    "--", \
  "docker-entrypoint.sh" \
]

CMD ["mysqld"]

tododb/Dockerfile の build 、更にタグ付けし、repositoryへpush

$ docker image build -t ch04/tododb:latest .

$ docker image tag ch04/tododb:latest localhost:5000/ch04/tododb:latest
$ docker image push localhost:5000/ch04/tododb:latest

Swarm上の Master/Slaveサービス定義 ($ vi stack/todo-mysql.yml )

version: "3"

services:
  master:
    image: registry:5000/ch04/tododb:latest
    deploy:
      replicas: 1
      placement:
        constraints: [node.role != manager]
    environment:
      MYSQL_ROOT_PASSWORD: gihyo 
      MYSQL_DATABASE: tododb 
      MYSQL_USER: gihyo 
      MYSQL_PASSWORD: gihyo 
      MYSQL_MASTER: "true" 
    networks:
      - todoapp

  slave:
    image: registry:5000/ch04/tododb:latest
    deploy:
      replicas: 2
      placement:
        constraints: [node.role != manager]
    depends_on:
      - master
    environment:
      MYSQL_MASTER_HOST: master
      MYSQL_DATABASE: tododb 
      MYSQL_USER: gihyo 
      MYSQL_PASSWORD: gihyo 
      MYSQL_ROOT_PASSWORD: gihyo 
      MYSQL_REPL_USER: repl 
      MYSQL_REPL_PASSWORD: gihyo 
    networks:
      - todoapp

networks:
  todoapp:
    external: true
$ docker container run -d --name todo_mysql localhost:5000/ch04/tododb:latest

$ docker container exec -it manager \
    docker stack deploy -c ./stack/todo-mysql.yml todo_mysql
ERROR open ./stack/todo-mysql.yml: no such file or directory