This post continues where part one left off. Topics include mysql data migration, staging and production docker configurations with optional https.
To perform these steps, you will need to either:
- Create the files directly on the server using nano, vim or some other command line editor.
- Create the files on your local machine and copy them to the server using scp.
I prefer the latter method. Creating the files locally in a folder structure that mirrors my home directory on the server makes it easier to edit and deploy them to the respective server. Not to mention the local backup this creates. Use scp from the command line or use a GUI application such as FileZilla or WinSCP.
For staging and production, create a
docker-compose.yml file that defines a reverse-proxy service using the official Traefik image. It is a good idea to put the Traefik Docker files in its own folder to make it easier when adding more sites later. Create a folder on the server for your Traefik files and save the compose yaml there.
version: "3" services: proxy: image: traefik restart: unless-stopped # command: --docker --logLevel=DEBUG command: --docker --logLevel=INFO networks: - webgateway ports: - "80:80" - "8080:8080" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./certs:/etc/traefik/certs # `chmod 600 acme.json` - ./acme.json:/etc/traefik/acme.json - ./traefik.toml:/etc/traefik/traefik.toml # - $PWD/.htpasswd:/etc/traefik/.htpasswd networks: webgateway: driver: bridge
- This Traefik
docker-compose.ymluses Let’s Encrypt for free SSL certificate renewal. Create a
acme.jsonfile to set that up. If you already have an SSL certificate for your site, use the
certsfolder to store the certificate files there for mounting to the Traefik container.
defaultEntryPoints = ["http", "https"] [entryPoints] [entryPoints.http] address = ":80" [entryPoints.https] address = ":443" [entryPoints.https.tls] # comment these lines if not in use # non let's encrypt certificates [[entryPoints.https.tls.certificates]] certFile = "/etc/traefik/certs/myothersite.com.crt" keyFile = "/etc/traefik/certs/myothersite.com.key" [acme] email = "email@example.com" storage = "acme.json" onHostRule = true # caServer = "http://172.18.0.1:4000/directory" entryPoint = "https" [acme.httpChallenge] entryPoint = "http"
- For staging, comment out the lines for https in
traefik.tomlas needed. More information on how to do this is included in my recent post: VPS Proof of Concept for Docker and Traefik.
acme.json file is used by Traefik for certificate storage. Create this file and set the permissions to 600 so only the owner can read and write. For example.
# change to the folder where our Traefik docker files are stored cd docker/traefik # create an empty acme.json file touch acme.json # set permissions to 600 chmod 600 acme.json
version: '2' services: app: image: mysite:4.9.6-1.0 restart: unless-stopped environment: - WORDPRESS_DB_HOST:mysql:3306 - WORDPRESS_DB_USER=wordpress - WORDPRESS_DB_PASSWORD=changeme! - WORDPRESS_DB_NAME=wordpress labels: - traefik.frontend.rule=Host:local.vm.mysite.com - traefik.docker.network=traefik_webgateway volumes: - app:/var/www/html networks: - web - backend links: - mysql mysql: image: mariadb restart: unless-stopped labels: - "traefik.enable=false" environment: - MYSQL_ROOT_PASSWORD=changeme! - MYSQL_DATABASE=wordpress - MYSQL_USER=wordpress - MYSQL_PASSWORD=changeme! volumes: - mysql:/var/lib/mysql networks: - backend networks: web: external: name: traefik_webgateway backend: driver: bridge volumes: app: mysql:
- For production, replace label
traefik.frontend.rule=Host:local.vm.mysite.comwith the registered host. You can specify both without and with
www, for example:
To recap, here is how we have structured our Docker files in the users home folder on the server for mounting them to volumes and running the containers with
docker/traefik/certs folder is only needed for non Let’s Encrypt certificate storage, for example, certificates purchased from SSLs.com. Note that we did not create an additional site, e.g.,
myothersite. It is included below only to demonstrate that multiple sites can be added using this setup and they can use either Let’s Encrypt or purchased certs.
Start the containers on the server using
docker-compose. Do this by opening a secure shell using
ssh. For example,
ssh firstname.lastname@example.org # change to the directory where you uploaded the # traefik docker-compose.yml file using scp cd docker/traefik # start the traefik container docker-compose up -d # change to the directory where you uploaded the # mysite docker-compose.yml file using scp cd docker/mysite # start the app and mysql containers defined in the mysite/docker-compose.yml docker-compose up -d
To view the site on staging, update your systems
hosts file to direct
local.vm.mysite.com requests to the staging server IP address. For example:
Load the site in a browser and install WordPress, for example, http://local.vm.mysite.com.
Once your WordPress site is installed, you may want to restore the data from another mysql volume. Perhaps your dev server has the data you now want on your staging instance of WordPress.
1. Perform a mysql dump to get the data from the running mysql container on the dev server. For example, using the development environment from part one, our container is named
# get the mysql container name by listing all of the containers docker ps -a # dump the mysql data into the current directory # from the running docker container named # my_wordpress_project_mariadb docker exec my_wordpress_project_mariadb /usr/bin/mysqldump -u root --password=password wordpress > wordpress.sql
2. Prepare your dev server mysql dump for loading into the staging server. Open the
wordpress.sql file in a code editor and replace all instances of the host:port with the staging server host. For example, replace
3. Upload the updated
wordpress.sql file to the staging server using
ssh into the staging server and load the
wordpress.sql into the running mysite mysql container.
# get the mysql container name by listing all of the containers docker ps -a # load the mysql data from the current directory # into the running mysite_mysql_1 docker container cat wordpress.sql | docker exec -i mysite_mysql_1 /usr/bin/mysql -u root --password=changeme! wordpress
- After loading a new Docker image, you will need to remove the pre-existing app volume before bringing up the app container for the new image. Use
docker volume lsto list the volumes and
docker volume rmto remove the app image. For example,
docker volume rm mysite_app.