A simple swarm stack to deploy wordpress in a docker swarm cluster. It uses below tools and docker images to deploy a wordpress setup.
Make sure you have a docker swarm cluster running. Then follow below commands:
# Clode the git repo
git clone https://github.com/iiriix/docker-swarm-wordpress
cd docker-swarm-wordpress
# Change 'example.com' to your own domain name
sed -i -e 's/example.com/yourdomain.com/g' ./docker-stack.yml
# Change default credentials in docker-stack.yml file
# Create required directories to persist data
mkdir -p /data/{wp,mysql,letsencrypt}_data
# Create docker networks
docker network create --driver overlay --scope swarm nw-web
docker network create --driver overlay --scope swarm nw-backend
# Deploy stack
docker stack deploy -c docker-stack.yml my_wordpress
# Check service status and logs
docker service ls
docker service logs -f my_wordpress_nginx
If that's the first time you're running it, it'll take a couple of minutes to fetch the docker images and initialize the database. When all the containers are running, open yourdomain.com
in your browser and proceed with the wordpress installation.
You can scale the wordpress
and nginx
part very easily:
# To scale up:
docker service scale my_wordpress_nginx=3
docker service scale my_wordpress_wordpress=3
# Check whether all replicas are running
docker service ls
# To scale down:
docker service scale my_wordpress_nginx=1
docker service scale my_wordpress_wordpress=1
It uses MySQL docker image and initializes the required database. However, if you don't want to use docker for your database, you can remove the mysql service from the docker-stack.yml
file and set the correct environment variables for wordpress database.
The traefik
service is configured to use Certbot (Letsencrypt)
to generate a wildcard valid SSL certificate for the domain in use. It uses dns challenge and is set to use cloudflare as the dns provider by default. However, you can configure it to use other providers (check here).
You need to set Cloudflare API Token using "CF_DNS_API_TOKEN"
env in docker-stack.yml
file in order to pass the dns challenge and get a valid certificate.
The certbot configuration is set to issue an staging certificate by default. If you want to get a production certificate, you need to comment below line in docker-stack.yml
:
- "--certificatesResolvers.myCloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory"
The nginx image is built to support fastcgi_cache
. It is configured to cache fpm responses for 10 minutes. If you change a content, in order to see the change, you need to either wait for 10 minutes for the cache to be dropped, or to drop the cache manually. A cache dropping mechanism is needed in the future. if you don't need caching, you can remove the relevant configurations form nginx config file (./apps/nginx/nginx_conf/conf.d/default.conf
).
php.ini
is mounted to the wordpress containers. In order to change parameters such as post_max_size
or upload_max_filesize
, just edit the file in ./apps/wordpress/php.ini
This stack has 3 volumes to persist the data and is set to use local storage driver by default. If you're deploying on a multi-node swarm cluster, use a suitable storage driver to mount the same volume on multiple containers.
/data/wp_data
: Keeps all wordpress files, themes, addons, .../data/mysql_data
: Keeps the database files/data/letsencrypt_data
: Keeps letsencrypt certificates that are generated by traefikBelow is a list of environment variables that you might need to change based on your needs.
Variable | Default Value | Description |
---|---|---|
MYSQL_DATABASE | wordpress | |
MYSQL_USER | wordpress | |
MYSQL_PASSWORD | wordpress | |
MYSQL_ROOT_PASSWORD | wordpressroot | |
WORDPRESS_DB_HOST | mysql | |
WORDPRESS_DB_USER | wordpress | should be set to the same value of MYSQL_USER |
WORDPRESS_DB_PASSWORD | wordpress | should be set to the same value of MYSQL_PASSWORD |
WORDPRESS_DB_NAME | wordpress | should be set to the same value of MYSQL_DATABASE |
WORDPRESS_TABLE_PREFIX | wp_ | |
CF_DNS_API_TOKEN | cloudflare_api_token | Set your own API Token |