Docker Cloud is a powerful tool that allows us to automate image builds, provision docker nodes, and create CI/CD pipelines. A month ago Docker introduced swarm mode for the Docker Cloud. And now teams and individuals can create and manage new or register their existing swarms and operate with them with docker id.

Our goal is to create a new swarm and deploy scalable WordPress.

Image.

Create a WP swarm

Before we begin we should link our docker cloud to Amazon Web Services. After this procedure, we can create swarms with several clicks.

Let’s create our WP swarm and choose EC2 instance type and a number of manager and worker nodes below (I hope Docker Team will add a possibility to select different instance types for labeled groups of worker nodes).

Docker Cloud Swarm Mode.

To persist our data we will use EFS and we should remember that only three regions offer efs support in NA.


After clicking the Create button it will take about five minutes to deploy swarm on Amazon. Docker Cloud uses CloudFormation template, the final result looks like this

Deploy Swarm on Amazon.

To get instructions on how to connect to the new swarm just click on it when the status changed to deploy.

Connect to the Swarm.

I’ve created swarm with three managers and two worker nodes:

$ docker node ls 
ID                           HOSTNAME                       STATUS  AVAILABILITY  MANAGER STATUS 
ah7s06zgqh04bq7vjvnlsp115    ip-172-31-36-181.ec2.internal  Ready   Active        Reachable 
lq3a5989rsykyofbuxvo9jzal *  ip-172-31-2-231.ec2.internal   Ready   Active        Leader 
mq31ffl0hj96549rch0b1jj5h    ip-172-31-28-121.ec2.internal  Ready   Active         
oe5wa3z87tz3smn8yrezl5y8p    ip-172-31-17-95.ec2.internal   Ready   Active        Reachable 
zkjm6xgfqubkr91fpe2lrhcfz    ip-172-31-0-161.ec2.internal   Ready   Active

Now let’s create temporary wordpress service to test our swarm.

We need secrets for our database:

$ openssl rand -base64 20 | docker secret create root_db_password -
$ openssl rand -base64 20 | docker secret create wp_db_password -

overlay network:

$ docker network create -d overlay wp

and MariaDB service:

$ docker service create \
    --name mariadb \
    --replicas 1 \
    --constraint=node.role==manager \
    --network wp \
    --secret source=root_db_password,target=root_db_password \
    --secret source=wp_db_password,target=wp_db_password \
    -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/root_db_password \
    -e MYSQL_PASSWORD_FILE=/run/secrets/wp_db_password \
    -e MYSQL_USER=wp \
    -e MYSQL_DATABASE=wp \
    mariadb:10.1
vx5c0fo9yuucpj50dx9up2xot
$ docker service ps mariadb  
ID            NAME       IMAGE         NODE                          DESIRED STATE  CURRENT STATE           ERROR  PORTS 
n8pnarl9x43b  mariadb.1  mariadb:10.1  ip-172-31-17-95.ec2.internal  Running        Running 19 seconds ago

And finally run WordPress:

$ docker service create \
    --name wp \
    --constraint=node.role==worker \
    --replicas 1 \
    --network wp \
    --publish 80:80 \
    --secret source=wp_db_password,target=wp_db_password,mode=0400 \
    -e WORDPRESS_DB_USER=wp \
    -e WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wp_db_password \
    -e WORDPRESS_DB_HOST=mariadb \
    -e WORDPRESS_DB_NAME=wp \
    wordpress:4.7
n5pruxiwz6ppr5dvqm5a6n33f

Every published port will be automatically added to the ELB entrypoint and we can proceed WP installation using web wizard:

WP Installation Using Web Wizard.

Fix issues

That’s simple and great but with this WordPress instance we have several issues:

  • No SSL
  • No Persistance
  • No Scalability (we can scale WordPress service, but wp-content will be different in all containers)

Let’s destroy this WP service and try to fix those issues with

$ docker service remove wp mariadb 
wp 
mariadb

If you deploy swarm to the EFS-compatible region Docker Cloud will install cloudstore:aws storage driver to every node, and this allows you to mount EFS storage as a docker volume. By default this driver uses general purpose EFS. For MariaDB service we will use maxio option. Also we will start traefik service to generate LetsEncrypt SSL and serve our vhost.

Here is our docker-stack.yml:

version: "3.1"services:traefik:
    image: traefik:1.2
    command: --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' --entryPoints='Name:https Address::443 TLS' --defaultEntryPoints=http,https --acme.entryPoint=https [email protected] --acme.storage=/etc/traefik/acme/acme.json --acme.domains=maddevs.io --acme.onHostRule=true --docker --docker.swarmmode --docker.domain=maddevs.io --docker.watch
    ports:
      - 80:80
      - 443:443
    volumes:
      - traefic_vol:/etc/traefik/acme
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - traefik
    deploy:
      placement:
          constraints: [node.role == manager]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failurewp:
    image: wordpress:latest
    volumes:
      - wp_content:/var/www/html/wp-content
    secrets:
      - wp_db_password
    environment:
      - WORDPRESS_DB_USER=wp
      - WORDPRESS_DB_NAME=wp
      - WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wp_db_password
      - WORDPRESS_DB_HOST=mariadb
    networks:
      - traefik
      - mariadb
    deploy:
      placement:
          constraints: [node.role == worker]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.backend.loadbalancer.swarm=true"
        - "traefik.port=80"
        - "traefik.frontend.rule=Host:wp.maddevs.io"
        - "traefik.docker.network=traefik"mariadb:
    image: mariadb
    volumes:
      - mariadb_vol:/var/lib/mysql
    secrets:
      - wp_db_password
      - root_db_password
    environment:
      - MYSQL_USER=wp
      - MYSQL_DATABASE=wp
      - MYSQL_PASSWORD_FILE=/run/secrets/wp_db_password
      - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/root_db_password
    networks:
      - mariadb
    deploy:
      placement:
          constraints: [node.role == manager]
      replicas: 1
      restart_policy:
        condition: on-failuresecrets:
  wp_db_password:
    external: true
  root_db_password:
    external: truevolumes:
  traefic_vol:
    driver: "cloudstor:aws"
  wp_content:
    driver: "cloudstor:aws"
  mariadb_vol:
    driver: "cloudstor:aws"
    driver_opts:
      perfmode: maxionetworks:
  traefik:
    external: true
  mariadb:
    external: true

Before start we should create CNAME wp.maddevs.io pointing to our ELB entrypoint. Then create networks and database secrets:

$ openssl rand -base64 20 | docker secret create root_db_password -
$ openssl rand -base64 20 | docker secret create wp_db_password -
$ docker network create -d overlay traefik
$ docker network create -d overlay mariadb

And deploy stack:

$ docker stack deploy -c docker-stack.yml wp
$ docker stack ps wp
ID            NAME              IMAGE             NODE                           DESIRED STATE  CURRENT STATE            ERROR                      PORTS
aruuw4nc5aog  wp_traefik.1      traefik:1.2       ip-172-31-17-95.ec2.internal   Running        Running 16 minutes ago                              
lwhjrhsq011x  wp_wp.1           wordpress:latest  ip-172-31-28-121.ec2.internal  Running        Running 16 minutes ago                              
jrddy5uksk3b  wp_mariadb.1      mariadb:latest    ip-172-31-2-231.ec2.internal   Running        Running 16 minutes ago

Now we can open our WordPress url https://wp.maddevs.io/ with http to https redirect.

And now we can scale traefik and wp manually:

$ docker service update --replicas 3 wp_traefik
$ docker service update --replicas 2 wp_wp
$ docker stack ps wp
ID            NAME              IMAGE             NODE                           DESIRED STATE  CURRENT STATE            ERROR                      PORTS
aruuw4nc5aog  wp_traefik.1      traefik:1.2       ip-172-31-17-95.ec2.internal   Running        Running 16 minutes ago                              
lwhjrhsq011x  wp_wp.1           wordpress:latest  ip-172-31-28-121.ec2.internal  Running        Running 16 minutes ago                              
jrddy5uksk3b  wp_mariadb.1      mariadb:latest    ip-172-31-2-231.ec2.internal   Running        Running 16 hours ago                                                               
r3t531anb8f0  wp_traefik.2      traefik:1.2       ip-172-31-36-181.ec2.internal  Running        Running 15 minutes ago                              
0gnadxbm32gt  wp_traefik.3      traefik:1.2       ip-172-31-2-231.ec2.internal   Running        Running 15 minutes ago                              
7yp7b6igimth  wp_wp.2           wordpress:latest  ip-172-31-0-161.ec2.internal   Running        Running 15 hours ago

Or by editing deploy section in our yml and redeploy stack.

Image.

We didn’t create more complicated infrastructure using another Amazon services like RDS, S3 + CloudFront, Elastic Cache etc but example above shows us the perfect symbiosis of cloud hosting and swarm mode with new docker >v1.13 features. Docker Cloud swarm mode removes our concerns about infrastructure and swarm management.

And it’s only beta.

Free Boilerplate to Run Kubernetes on AWS.
Android CI/CD boilerplate for publishing via Fastlane

How to Automate CI/CD for Android App with Boilerplate

How to Automate CI/CD for Android App...

How to Automate CI/CD for Android App with Boilerplate

Stop publishing your Android apps manually and start doing this fully automated at any stage.Mobile development, as well as any other software...

Cloud Cost Optimization

Cloud Cost Optimization: How to Reduce Your Cloud Bill

Cloud Cost Optimization: How to...

Cloud Cost Optimization: How to Reduce Your Cloud Bill

This is not surprising because, in 2024, 80% of companies will be unaware of their mistakes in their cloud adoption and will overspend by 20 to 50%....

What DevOps toolchain is and how to build one

What DevOps Toolchain Is and How to Build One

What DevOps Toolchain Is and How to...

What DevOps Toolchain Is and How to Build One

Tech organizations are constantly competing to outperform each other. As technology keeps advancing rapidly, these organizations must stay ahead of...