Today I had a dream, as if I had been squeezed down to the size of several
kilobyte, stuck in some socket and run in a container.
Highlighted transport in the overlay network and allowed
test services in other containers ...
Docker rm is not done yet.
export DOCKER_HOST=tcp://<my_swarm_ip>:3375
docker daemon --label com.example.storage="ssd"
docker run -d -e constraint:com.example.storage="ssd" postgres
#!/usr/bin/with-contenv sh RESULT=`redis-cli ping` if [ "$RESULT" = "PONG" ]; then exit 0 fi exit 2
{ "check": { "id": "mem-util", "name": "Memory utilization", "script": "/usr/local/bin/check_mem.py", "interval": "10s" } }
{ "id": "ssh", "name": "SSH TCP on port 22", "tcp": "127.0.0.1:22", "interval": "10s", "timeout": "1s" }
docker run -p 8088:3000 -d --name uwsgi-worker --link consul:consul -l "SERVICE_NAME=uwsgi-worker" -l "SERVICE_TAGS=django" \ -l "SERVICE_3000_CHECK_HTTP=/" -l "SERVICE_3000_CHECK_INTERVAL=15s" -l "SERVICE_3000_CHECK_TIMEOUT=1s" uwsgi-worker
curl http://<consul_ip>:8500/v1/health/service/uwsgi-worker | jq .
[ { "Node": { "Node": "docker0", "Address": "127.0.0.1", "CreateIndex": 370, "ModifyIndex": 159636 }, "Service": { "ID": "docker0:uwsgi-worker:3000", "Service": "uwsgi-worker", "Tags": [ "django" ], "Address": "127.0.0.1", "Port": 8088, "EnableTagOverride": false, "CreateIndex": 159631, "ModifyIndex": 159636 }, "Checks": [ { "Node": "docker0", "CheckID": "serfHealth", "Name": "Serf Health Status", "Status": "passing", "Notes": "", "Output": "Agent alive and reachable", "ServiceID": "", "ServiceName": "", "CreateIndex": 370, "ModifyIndex": 370 }, { "Node": "docker0", "CheckID": "service:docker1:uwsgi-worker:3000", "Name": "Service 'uwsgi-worker' check", "Status": "passing", "Notes": "", "Output": "", "ServiceID": "docker0:uwsgi-worker:3000", "ServiceName": "uwsgi-worker", "CreateIndex": 159631, "ModifyIndex": 159636 } ] } ]
curl -XPUT -d @_ssh_check.json http://<consul_ip>:8500/v1/agent/check/register
{ "id": "ssh", "name": "SSH TCP on port 22", "tcp": "<your_ip>:22", "interval": "10s", "timeout": "1s" }
curl http://<consul_ip>:8500/v1/agent/check/deregister/ssh_check
docker run --restart=unless-stopped -v /root/html:/usr/share/nginx/html:ro --links consul:consul -l "SERVICE_NAME=nginx" -l "SERVICE_TAGS=web" -l "SERVICE_CHECK_HTTP=/" -l "SERVICE_CHECK_INTERVAL=15s" -l "SERVICE_CHECK_TIMEOUT=1s" -p 8080:80 -d nginx
upstream fpm { least_conn; {{range service "php"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1; {{else}}server 127.0.0.1:65535{{end}} } server { listen 80; root /var/www/html; index index.php index.html index.htm; server_name your.domain.com; sendfile off; location / { } location ~ \.php$ { fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass fpm; fastcgi_index index.php; include fastcgi_params; } }
consul-template -consul <your_consul_ip>:8500 -template server.conf.ctmpl -once -dry
upstream fpm { least_conn; server 127.0.0.1:9000 max_fails=3 fail_timeout=60 weight=1; } server { listen 80; root /var/www/html; index index.php index.html index.htm; server_name your.domain.com; sendfile off; location / { } location ~ \.php$ { fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass fpm; fastcgi_index index.php; include fastcgi_params; } }
consul-template -consul <your_consul_ip>:8500 -template server.conf.ctmpl:/etc/nginx/conf.d/server.conf:service nginx reload
echo "deb http://apt.dockerproject.org/repo debian-jessie main" > /etc/apt/sources.list.d/docker.list
apt-get update apt-get install ca-certificates apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D apt-get update apt-get install docker-engine aufs-tools
docker run --restart=unless-stopped -d -h `hostname` --name consul -v /mnt:/data \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8300:8300 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8301:8301 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8301:8301/udp \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8302:8302 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8302:8302/udp \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8400:8400 \ -p 8500:8500 \ -p 172.17.0.1:53:53/udp \ gliderlabs/consul-server -server -rejoin -advertise `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` -bootstrap
ExecStart=/usr/bin/docker daemon -H fd:// -H tcp://<your_ip>:2375 --storage-driver=aufs --cluster-store=consul://<your_ip>:8500 --cluster-advertise <your_ip>:2375
systemctl daemon-reload service docker restart
docker ps
docker run --restart=unless-stopped -d \ -p 3375:2375 \ swarm manage \ --replication \ --advertise `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:3375 \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500/
docker run --restart=unless-stopped -d \ swarm join \ --advertise=`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:2375 \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500/
docker run --restart=unless-stopped -d \ --name=registrator \ --net=host \ --volume=/var/run/docker.sock:/tmp/docker.sock \ gliderlabs/registrator:latest \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500
docker run --restart=unless-stopped -d -h `hostname` --name consul -v /mnt:/data \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8300:8300 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8301:8301 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8301:8301/udp \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8302:8302 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8302:8302/udp \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8400:8400 \ -p `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500:8500 \ -p 172.17.0.1:53:53/udp \ gliderlabs/consul-server -server -rejoin -advertise `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` -join <primary_node_ip>
docker run --restart=unless-stopped -d \ -p 3375:2375 \ swarm manage \ --advertise `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:3375 \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500/
docker run --restart=unless-stopped -d \ swarm join \ --advertise=`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:2375 \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500/
docker run --restart=unless-stopped -d \ --name=registrator \ --net=host \ --volume=/var/run/docker.sock:/tmp/docker.sock \ gliderlabs/registrator:latest \ -ip `ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` \ consul://`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`:8500
docker stop $(docker ps -aq);docker start $(docker ps -aq)
docker stop $(docker ps -aq);docker rm $(docker ps -aq)
docker stop $(docker ps -a | grep 'Exited' | awk '{print $1}') && docker rm $(docker ps -a | grep 'Exited' | awk '{print $1}')
docker volume rm $(docker volume ls -q);
docker rmi $(docker images -q);
export DOCKER_HOST=tcp://<my_swarm_ip>:3375
FROM phusion/baseimage:0.9.18 ENV NGINX_VERSION 1.8.1-1~trusty ENV DEBIAN_FRONTEND=noninteractive # Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start. RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d RUN curl -sS http://nginx.org/keys/nginx_signing.key | sudo apt-key add - && \ echo 'deb http://nginx.org/packages/ubuntu/ trusty nginx' >> /etc/apt/sources.list && \ echo 'deb-src http://nginx.org/packages/ubuntu/ trusty nginx' >> /etc/apt/sources.list && \ apt-get update -qq && apt-get install -y unzip ca-certificates nginx=${NGINX_VERSION} && \ rm -rf /var/lib/apt/lists/* && \ ln -sf /dev/stdout /var/log/nginx/access.log && \ ln -sf /dev/stderr /var/log/nginx/error.log EXPOSE 80 # Consul Template ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/ RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin ADD nginx.service /etc/service/nginx/run RUN chmod a+x /etc/service/nginx/run ADD consul-template.service /etc/service/consul-template/run RUN chmod a+x /etc/service/consul-template/run RUN rm -v /etc/nginx/conf.d/*.conf ADD app.conf.ctmpl /etc/consul-templates/app.conf.ctmpl CMD ["/sbin/my_init"]
#!/bin/sh /usr/sbin/nginx -c /etc/nginx/nginx.conf -t && \ exec /usr/sbin/nginx -c /etc/nginx/nginx.conf -g "daemon off;"
#!/bin/sh exec /usr/local/bin/consul-template \ -consul consul:8500 \ -template "/etc/consul-templates/app.conf.ctmpl:/etc/nginx/conf.d/app.conf:sv hup nginx || true"
upstream fpm { least_conn; {{range service "fpm"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1; {{else}}server 127.0.0.1:65535{{end}} } server { listen 80; root /var/www/html; index index.php index.html index.htm; server_name domain.example.com; sendfile off; location / { try_files $uri $uri/ /index.php?q=$uri&$args; } location /doc/ { alias /usr/share/doc/; autoindex on; allow 127.0.0.1; allow ::1; deny all; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/www; } location ~ \.php$ { try_files $uri =404; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass fpm; fastcgi_index index.php; include fastcgi_params; } location ~ /\.ht { deny all; } }
docker build -t nginx-lb .
docker run -p 80:80 -v /mnt/storage/www:/var/www/html -d --name balancer --link consul:consul -l "SERVICE_NAME=balancer" -l "SERVICE_TAGS=balancer" \ -l "SERVICE_CHECK_HTTP=/" -l "SERVICE_CHECK_INTERVAL=15s" -l "SERVICE_CHECK_TIMEOUT=1s" nginx-lb
FROM php:5.6-fpm # install the PHP extensions we need RUN apt-get update && apt-get install -y unzip libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ && docker-php-ext-install gd mysqli opcache # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=60'; \ echo 'opcache.fast_shutdown=1'; \ echo 'opcache.enable_cli=1'; \ } > /usr/local/etc/php/conf.d/opcache-recommended.ini VOLUME /var/www/html ENV WORDPRESS_VERSION 4.4.2 ENV WORDPRESS_SHA1 7444099fec298b599eb026e83227462bcdf312a6 # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress RUN curl -o wordpress.tar.gz -SL https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz \ && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ && tar -xzf wordpress.tar.gz -C /usr/src/ \ && rm wordpress.tar.gz \ && chown -R www-data:www-data /usr/src/wordpress ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/ RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin # . ADD db.conf.php.ctmpl /db.conf.php.ctmpl # consul-template ADD consul-template.sh /usr/local/bin/consul-template.sh # MySQL WP ADD mysql.ctmpl /tmp/mysql.ctmpl COPY docker-entrypoint.sh /entrypoint.sh # grr, ENTRYPOINT resets CMD now ENTRYPOINT ["/entrypoint.sh"] CMD ["php-fpm"]
<?php {{range service "mysql"}} define('DB_HOST', '{{.Address}}'); {{else}} define('DB_HOST', 'mysql'); {{end}} ?>
#!/bin/sh echo "Starting Consul Template" exec /usr/local/bin/consul-template \ -consul consul:8500 \ -template "/db.conf.php.ctmpl:/var/www/html/db.conf.php"
{{range service "mysql"}}{{.Address}} {{.Port}} {{end}}
#!/bin/bash set -e # WORDPRESS_DB_HOST="$(/usr/local/bin/consul-template --template=/tmp/mysql-master.ctmpl --consul=consul:8500 --dry -once | awk '{print $1}' | tail -1)" # WORDPRESS_DB_PORT="$(/usr/local/bin/consul-template --template=/tmp/mysql-master.ctmpl --consul=consul:8500 --dry -once | awk '{print $2}' | tail -1)" if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then if [ -n "$MYSQL_PORT_3306_TCP" ]; then if [ -z "$WORDPRESS_DB_HOST" ]; then WORDPRESS_DB_HOST='mysql' else echo >&2 'warning: both WORDPRESS_DB_HOST and MYSQL_PORT_3306_TCP found' echo >&2 " Connecting to WORDPRESS_DB_HOST ($WORDPRESS_DB_HOST)" echo >&2 ' instead of the linked mysql container' fi fi if [ -z "$WORDPRESS_DB_HOST" ]; then echo >&2 'error: missing WORDPRESS_DB_HOST and MYSQL_PORT_3306_TCP environment variables' echo >&2 ' Did you forget to --link some_mysql_container:mysql or set an external db' echo >&2 ' with -e WORDPRESS_DB_HOST=hostname:port?' exit 1 fi # if we're linked to MySQL and thus have credentials already, let's use them : ${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}} if [ "$WORDPRESS_DB_USER" = 'root' ]; then : ${WORDPRESS_DB_PASSWORD:=$MYSQL_ENV_MYSQL_ROOT_PASSWORD} fi : ${WORDPRESS_DB_PASSWORD:=$MYSQL_ENV_MYSQL_PASSWORD} : ${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-wordpress}} if [ -z "$WORDPRESS_DB_PASSWORD" ]; then echo >&2 'error: missing required WORDPRESS_DB_PASSWORD environment variable' echo >&2 ' Did you forget to -e WORDPRESS_DB_PASSWORD=... ?' echo >&2 echo >&2 ' (Also of interest might be WORDPRESS_DB_USER and WORDPRESS_DB_NAME.)' exit 1 fi if ! [ -e index.php -a -e wp-includes/version.php ]; then echo >&2 "WordPress not found in $(pwd) - copying now..." if [ "$(ls -A)" ]; then echo >&2 "WARNING: $(pwd) is not empty - press Ctrl+C now if this is an error!" ( set -x; ls -A; sleep 10 ) fi tar cf - --one-file-system -C /usr/src/wordpress . | tar xf - echo >&2 "Complete! WordPress has been successfully copied to $(pwd)" if [ ! -e .htaccess ]; then # NOTE: The "Indexes" option is disabled in the php:apache base image cat > .htaccess <<-'EOF' # BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress EOF chown www-data:www-data .htaccess fi fi # TODO handle WordPress upgrades magically in the same way, but only if wp-includes/version.php's $wp_version is less than /usr/src/wordpress/wp-includes/version.php's $wp_version # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks # https://github.com/docker-library/wordpress/issues/116 # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 sed -ri 's/\r\n|\r/\n/g' wp-config* # FPM 0.0.0.0 sed -i 's/listen = 127.0.0.1:9000/listen = 0.0.0.0:9000/g' /usr/local/etc/php-fpm.d/www.conf if [ ! -e wp-config.php ]; then awk '/^\/\*.*stop editing.*\*\/$/ && c == 0 { c = 1; system("cat") } { print }' wp-config-sample.php > wp-config.php <<'EOPHP' // If we're behind a proxy server and using HTTPS, we need to alert Wordpress of that fact // see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; } EOPHP # Consul Template MySQL DB_HOST_PRE=$(grep 'DB_HOST' wp-config.php) sed -i "s/$DB_HOST_PRE/include 'db.conf.php';/g" wp-config.php chown www-data:www-data wp-config.php fi # see http://stackoverflow.com/a/2705678/433558 sed_escape_lhs() { echo "$@" | sed 's/[]\/$*.^|[]/\\&/g' } sed_escape_rhs() { echo "$@" | sed 's/[\/&]/\\&/g' } php_escape() { php -r 'var_export(('$2') $argv[1]);' "$1" } set_config() { key="$1" value="$2" var_type="${3:-string}" start="(['\"])$(sed_escape_lhs "$key")\2\s*," end="\);" if [ "${key:0:1}" = '$' ]; then start="^(\s*)$(sed_escape_lhs "$key")\s*=" end=";" fi sed -ri "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php } set_config 'DB_HOST' "$WORDPRESS_DB_HOST" set_config 'DB_USER' "$WORDPRESS_DB_USER" set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" set_config 'DB_NAME' "$WORDPRESS_DB_NAME" # allow any of these "Authentication Unique Keys and Salts." to be specified via # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") UNIQUES=( AUTH_KEY SECURE_AUTH_KEY LOGGED_IN_KEY NONCE_KEY AUTH_SALT SECURE_AUTH_SALT LOGGED_IN_SALT NONCE_SALT ) for unique in "${UNIQUES[@]}"; do eval unique_value=\$WORDPRESS_$unique if [ "$unique_value" ]; then set_config "$unique" "$unique_value" else # if not specified, let's generate a random value current_set="$(sed -rn "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done if [ "$WORDPRESS_TABLE_PREFIX" ]; then set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" fi if [ "$WORDPRESS_DEBUG" ]; then set_config 'WP_DEBUG' 1 boolean fi TERM=dumb php -- "$WORDPRESS_DB_HOST" "$WORDPRESS_DB_USER" "$WORDPRESS_DB_PASSWORD" "$WORDPRESS_DB_NAME" <<'EOPHP' <?php // database might not exist, so let's try creating it (just to be safe) $stderr = fopen('php://stderr', 'w'); list($host, $port) = explode(':', $argv[1], 2); $maxTries = 10; do { $mysql = new mysqli($host, $argv[2], $argv[3], '', (int)$port); if ($mysql->connect_error) { fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); --$maxTries; if ($maxTries <= 0) { exit(1); } sleep(3); } } while ($mysql->connect_error); if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($argv[4]) . '`')) { fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); $mysql->close(); exit(1); } $mysql->close(); EOPHP fi # consul-template exec /usr/local/sbin/php-fpm & exec /usr/local/bin/consul-template.sh exec "$@"
docker build -t fpm .
docker run --name fpm.0 -d -v /mnt/storage/www:/var/www/html \ -e WORDPRESS_DB_NAME=wordpressp -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress \ --link consul:consul -l "SERVICE_NAME=php-fpm" -l "SERVICE_PORT=9000" -p 9000:9000 fpm
FROM debian:jessie # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mysql && useradd -r -g mysql mysql RUN mkdir /docker-entrypoint-initdb.d # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db: # File::Basename # File::Copy # Sys::Hostname # Data::Dumper RUN apt-get update && apt-get install -y perl pwgen --no-install-recommends && rm -rf /var/lib/apt/lists/* # gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 ENV MYSQL_MAJOR 5.7 ENV MYSQL_VERSION 5.7.11-1debian8 RUN echo "deb http://repo.mysql.com/apt/debian/ jessie mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list # the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql) # also, we set debconf keys to make APT a little quieter RUN { \ echo mysql-community-server mysql-community-server/data-dir select ''; \ echo mysql-community-server mysql-community-server/root-pass password ''; \ echo mysql-community-server mysql-community-server/re-root-pass password ''; \ echo mysql-community-server mysql-community-server/remove-test-db select false; \ } | debconf-set-selections \ && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql # comment out a few problematic configuration values # don't reverse lookup hostnames, they are usually another container RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ && mv /tmp/my.cnf /etc/mysql/my.cnf VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"]
#!/bin/bash set -eo pipefail # if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" fi if [ "$1" = 'mysqld' ]; then # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then echo >&2 'error: database is uninitialized and password option is not specified ' echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD' exit 1 fi mkdir -p "$DATADIR" chown -R mysql:mysql "$DATADIR" echo 'Initializing database' "$@" --initialize-insecure echo 'Database initialized' "$@" --skip-networking & pid="$!" mysql=( mysql --protocol=socket -uroot ) for i in {30..0}; do if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then break fi echo 'MySQL init process in progress...' sleep 1 done if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi if [ -n "${REPLICATION_MASTER}" ]; then echo "=> Configuring MySQL replication as master (1/2) ..." if [ ! -f /replication_set.1 ]; then echo "=> Writting configuration file /etc/mysql/my.cnf with server-id=1" echo 'server-id = 1' >> /etc/mysql/my.cnf echo 'log-bin = mysql-bin' >> /etc/mysql/my.cnf touch /replication_set.1 else echo "=> MySQL replication master already configured, skip" fi fi # Set MySQL REPLICATION - SLAVE if [ -n "${REPLICATION_SLAVE}" ]; then echo "=> Configuring MySQL replication as slave (1/2) ..." if [ -n "${MYSQL_PORT_3306_TCP_ADDR}" ] && [ -n "${MYSQL_PORT_3306_TCP_PORT}" ]; then if [ ! -f /replication_set.1 ]; then echo "=> Writting configuration file /etc/mysql/my.cnf with server-id=2" echo 'server-id = 2' >> /etc/mysql/my.cnf echo 'log-bin = mysql-bin' >> /etc/mysql/my.cnf echo 'log-bin=slave-bin' >> /etc/mysql/my.cnf touch /replication_set.1 else echo "=> MySQL replication slave already configured, skip" fi else echo "=> Cannot configure slave, please link it to another MySQL container with alias as 'mysql'" exit 1 fi fi # Set MySQL REPLICATION - SLAVE if [ -n "${REPLICATION_SLAVE}" ]; then echo "=> Configuring MySQL replication as slave (2/2) ..." if [ -n "${MYSQL_PORT_3306_TCP_ADDR}" ] && [ -n "${MYSQL_PORT_3306_TCP_PORT}" ]; then if [ ! -f /replication_set.2 ]; then echo "=> Setting master connection info on slave" echo "!!! DEBUG: ${REPLICATION_USER}, ${REPLICATION_PASS}." "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; CHANGE MASTER TO MASTER_HOST='${MYSQL_PORT_3306_TCP_ADDR}',MASTER_USER='${REPLICATION_USER}',MASTER_PASSWORD='${REPLICATION_PASS}',MASTER_PORT=${MYSQL_PORT_3306_TCP_PORT}, MASTER_CONNECT_RETRY=30; START SLAVE ; EOSQL echo "=> Done!" touch /replication_set.2 else echo "=> MySQL replication slave already configured, skip" fi else echo "=> Cannot configure slave, please link it to another MySQL container with alias as 'mysql'" exit 1 fi fi if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then # sed is for https://bugs.mysql.com/bug.php?id=20545 mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql fi if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" fi "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; DELETE FROM mysql.user ; CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; DROP DATABASE IF EXISTS test ; FLUSH PRIVILEGES ; EOSQL if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) fi # Set MySQL REPLICATION - MASTER if [ -n "${REPLICATION_MASTER}" ]; then echo "=> Configuring MySQL replication as master (2/2) ..." if [ ! -f /replication_set.2 ]; then echo "=> Creating a log user ${REPLICATION_USER}:${REPLICATION_PASS}" "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; CREATE USER '${REPLICATION_USER}'@'%' IDENTIFIED BY '${REPLICATION_PASS}'; GRANT REPLICATION SLAVE ON *.* TO '${REPLICATION_USER}'@'%' ; FLUSH PRIVILEGES ; RESET MASTER ; EOSQL echo "=> Done!" touch /replication_set.2 else echo "=> MySQL replication master already configured, skip" fi fi if [ "$MYSQL_DATABASE" ]; then echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" mysql+=( "$MYSQL_DATABASE" ) fi if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" fi echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi echo for f in /docker-entrypoint-initdb.d/*; do case "$f" in *.sh) echo "$0: running $f"; . "$f" ;; *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; *) echo "$0: ignoring $f" ;; esac echo done if [ ! -z "$MYSQL_ONETIME_PASSWORD" ]; then "${mysql[@]}" <<-EOSQL ALTER USER 'root'@'%' PASSWORD EXPIRE; EOSQL fi if ! kill -s TERM "$pid" || ! wait "$pid"; then echo >&2 'MySQL init process failed.' exit 1 fi echo echo 'MySQL init process done. Ready for start up.' echo fi chown -R mysql:mysql "$DATADIR" fi exec "$@"
docker build -t mysql-master .
docker run --name mysql-master.0 -v /mnt/volumes/master:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=rootpass -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=wordpress -e MYSQL_DB=wordpress -e REPLICATION_MASTER=true -e REPLICATION_USER=replica -e REPLICATION_PASS=replica --link consul:consul -l "SERVICE_NAME=master" -l "SERVICE_PORT=3306" -p 3306:3306 -d mysql-master
FROM debian:jessie # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mysql && useradd -r -g mysql mysql RUN mkdir /docker-entrypoint-initdb.d # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db: # File::Basename # File::Copy # Sys::Hostname # Data::Dumper RUN apt-get update && apt-get install -y perl pwgen --no-install-recommends && rm -rf /var/lib/apt/lists/* # gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 ENV MYSQL_MAJOR 5.7 ENV MYSQL_VERSION 5.7.11-1debian8 RUN echo "deb http://repo.mysql.com/apt/debian/ jessie mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list # the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql) # also, we set debconf keys to make APT a little quieter RUN { \ echo mysql-community-server mysql-community-server/data-dir select ''; \ echo mysql-community-server mysql-community-server/root-pass password ''; \ echo mysql-community-server mysql-community-server/re-root-pass password ''; \ echo mysql-community-server mysql-community-server/remove-test-db select false; \ } | debconf-set-selections \ && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql # comment out a few problematic configuration values # don't reverse lookup hostnames, they are usually another container RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ && mv /tmp/my.cnf /etc/mysql/my.cnf ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/ RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin ADD mysql-master.ctmpl /tmp/mysql-master.ctmpl VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"]
#!/bin/bash set -eo pipefail # Consul, master MYSQL_PORT_3306_TCP_ADDR="$(/usr/bin/consul-template --template=/tmp/mysql-master.ctmpl --consul=consul:8500 --dry -once | awk '{print $1}' | tail -1)" MYSQL_PORT_3306_TCP_PORT="$(/usr/bin/consul-template --template=/tmp/mysql-master.ctmpl --consul=consul:8500 --dry -once | awk '{print $2}' | tail -1)" if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" fi if [ "$1" = 'mysqld' ]; then # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then echo >&2 'error: database is uninitialized and password option is not specified ' echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD' exit 1 fi mkdir -p "$DATADIR" chown -R mysql:mysql "$DATADIR" echo 'Initializing database' "$@" --initialize-insecure echo 'Database initialized' "$@" --skip-networking & pid="$!" mysql=( mysql --protocol=socket -uroot ) for i in {30..0}; do if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then break fi echo 'MySQL init process in progress...' sleep 1 done if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi if [ -n "${REPLICATION_MASTER}" ]; then echo "=> Configuring MySQL replication as master (1/2) ..." if [ ! -f /replication_set.1 ]; then echo "=> Writting configuration file /etc/mysql/my.cnf with server-id=1" echo 'server-id = 1' >> /etc/mysql/my.cnf echo 'log-bin = mysql-bin' >> /etc/mysql/my.cnf touch /replication_set.1 else echo "=> MySQL replication master already configured, skip" fi fi # Set MySQL REPLICATION - SLAVE if [ -n "${REPLICATION_SLAVE}" ]; then echo "=> Configuring MySQL replication as slave (1/2) ..." if [ -n "${MYSQL_PORT_3306_TCP_ADDR}" ] && [ -n "${MYSQL_PORT_3306_TCP_PORT}" ]; then if [ ! -f /replication_set.1 ]; then echo "=> Writting configuration file /etc/mysql/my.cnf with server-id=2" echo 'server-id = 2' >> /etc/mysql/my.cnf echo 'log-bin = mysql-bin' >> /etc/mysql/my.cnf echo 'log-bin=slave-bin' >> /etc/mysql/my.cnf touch /replication_set.1 else echo "=> MySQL replication slave already configured, skip" fi else echo "=> Cannot configure slave, please link it to another MySQL container with alias as 'mysql'" exit 1 fi fi # Set MySQL REPLICATION - SLAVE if [ -n "${REPLICATION_SLAVE}" ]; then echo "=> Configuring MySQL replication as slave (2/2) ..." if [ -n "${MYSQL_PORT_3306_TCP_ADDR}" ] && [ -n "${MYSQL_PORT_3306_TCP_PORT}" ]; then if [ ! -f /replication_set.2 ]; then echo "=> Setting master connection info on slave" "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; CHANGE MASTER TO MASTER_HOST='${MYSQL_PORT_3306_TCP_ADDR}',MASTER_USER='${REPLICATION_USER}',MASTER_PASSWORD='${REPLICATION_PASS}',MASTER_PORT=${MYSQL_PORT_3306_TCP_PORT}, MASTER_CONNECT_RETRY=30; START SLAVE ; EOSQL echo "=> Done!" touch /replication_set.2 else echo "=> MySQL replication slave already configured, skip" fi else echo "=> Cannot configure slave, please link it to another MySQL container with alias as 'mysql'" exit 1 fi fi if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then # sed is for https://bugs.mysql.com/bug.php?id=20545 mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql fi if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" fi "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; DELETE FROM mysql.user ; CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; DROP DATABASE IF EXISTS test ; FLUSH PRIVILEGES ; EOSQL if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) fi # Set MySQL REPLICATION - MASTER if [ -n "${REPLICATION_MASTER}" ]; then echo "=> Configuring MySQL replication as master (2/2) ..." if [ ! -f /replication_set.2 ]; then echo "=> Creating a log user ${REPLICATION_USER}:${REPLICATION_PASS}" "${mysql[@]}" <<-EOSQL -- What's done in this file shouldn't be replicated -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; CREATE USER '${REPLICATION_USER}'@'%' IDENTIFIED BY '${REPLICATION_PASS}'; GRANT REPLICATION SLAVE ON *.* TO '${REPLICATION_USER}'@'%' ; FLUSH PRIVILEGES ; RESET MASTER ; EOSQL echo "=> Done!" touch /replication_set.2 else echo "=> MySQL replication master already configured, skip" fi fi if [ "$MYSQL_DATABASE" ]; then echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" mysql+=( "$MYSQL_DATABASE" ) fi if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" fi echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi echo for f in /docker-entrypoint-initdb.d/*; do case "$f" in *.sh) echo "$0: running $f"; . "$f" ;; *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; *) echo "$0: ignoring $f" ;; esac echo done if [ ! -z "$MYSQL_ONETIME_PASSWORD" ]; then "${mysql[@]}" <<-EOSQL ALTER USER 'root'@'%' PASSWORD EXPIRE; EOSQL fi if ! kill -s TERM "$pid" || ! wait "$pid"; then echo >&2 'MySQL init process failed.' exit 1 fi echo echo 'MySQL init process done. Ready for start up.' echo fi chown -R mysql:mysql "$DATADIR" fi exec "$@"
{{range service "master"}}{{.Address}} {{.Port}} {{end}}
docker build -t mysql-slave .
docker run --name mysql-slave.0 -v /mnt/volumes/slave:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=rootpass -e REPLICATION_SLAVE=true -e REPLICATION_USER=replica -e REPLICATION_PASS=replica --link=consul:consul -l "SERVICE_NAME=slave" -l "SERVICE_PORT=3307" -p 3307:3306 -d mysql-slave
docker run --name fpm.0 -d -v /mnt/storage/www:/var/www/html \ -e WORDPRESS_DB_NAME=wordpressp -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress \ --link consul:consul -l "SERVICE_NAME=php-fpm" -l "SERVICE_PORT=9000" -l "SERVICE_TAGS=worker" -p 9000:9000 fpm
docker logs <container_name>
mysql-master: image: mysql-master ports: - "3306:3306" environment: - "MYSQL_DATABASE=wp" - "MYSQL_USER=wordpress" - "MYSQL_PASSWORD=wordpress" - "REPLICATION_MASTER=true" - "REPLICATION_USER=replica" - "REPLICATION_PASS=replica" external_links: - consul:consul labels: - "SERVICE_NAME=mysql-master" - "SERVICE_PORT=3306" - "SERVICE_TAGS=db" volumes: - '/mnt/storage/master:/var/lib/mysql' mysql-slave: image: mysql-slave ports: - "3307:3306" environment: - "REPLICATION_SLAVE=true" - "REPLICATION_USER=replica" - "REPLICATION_PASS=replica" external_links: - consul:consul labels: - "SERVICE_NAME=mysql-slave" - "SERVICE_PORT=3307" - "SERVICE_TAGS=db" volumes: - '/mnt/storage/slave:/var/lib/mysql' wordpress: image: fpm ports: - "9000:9000" environment: - "WORDPRESS_DB_NAME=wp" - "WORDPRESS_DB_USER=wordpress" - "WORDPRESS_DB_PASSWORD=wordpress" external_links: - consul:consul labels: - "SERVICE_NAME=php-fpm" - "SERVICE_PORT=9000" - "SERVICE_TAGS=worker" volumes: - '/mnt/storage/www:/var/www/html'
docker-compose up
Source: https://habr.com/ru/post/278939/
All Articles