At Stealthwerk, we're starting a new project and using Docker to have a consistent development environment for all our developers. I'll be acting as the lead developer on this project so one of my top priorities is to spend as little time as possible dealing with environment setup and any issues people might have from their individual configurations. We also have an apprentice on the team, so less seasoned developers should be able to get started with no problem as well. Our project looks something like this:
- We have a Wordpress folder checked into Git
- We do not want to use the Wordpress image. We just want to have Apache, PHP, and MySQL that runs the Wordpress in the folder
- We use WP Migrate DB on our Dev server to download a MySQL file periodically. Workflow is:
1. Do Migrate DB on Dev server and download the SQL file 2. Import this into local MySQL 3. Make any changes and work locally 4. Make Wordpress changes on the Dev server to save them. Repeat these 4 steps.
- The local DB should be ephemeral. We always want the latest version of the Dev MySQL database to work off of. We make our changes on the Dev server so that all the other developers
can pull our changes.
Issues to Note With Docker
As many are aware, Docker does not work on Mac OSX natively. Instead it runs through a tool called boot2docker. When you install Docker for Mac OSX, this is what's being installed. There's a couple of differences between this implementation and regular Docker. The most important one which took me a while to figure out was that by default, Docker only gets access to your /Users folder. That is what is shared through Virtualbox. That means you can't work off of a folder outside the /Users folder by default.
Data is not permanent. Each time you restart a container, your data is lost.
The official PHP Docker image does not contain the MySQL extension.
If you want to work on your code in realtime, meaning your changes will show up as soon as you make them, then you need to mount your Wordpress directory as a volume. If you do this though, Wordpress will throw you a lot of file permissions errors. This is because your files are owned as your user but PHP runs as www-data. This means you can't install plugins, upload images, etc.
You will regularly get messages like
To perform the requested action, WordPress needs to access your web server. Please enter your FTP credentials to proceed. If you do not remember your credentials, you should contact your web host.
For wp-config.php, you need a DB Host (e.g. localhost). With Docker, you need to specify an IP address. I feel I missed something for this step because linking the container to PHP should give us the DB host as seen in other examples. In my case, it did not work and I came up with a workaround. I saw some solutions recommend doing docker inspect, running a bridge, etc. I didn't want to do any of those. My workaround was to use phpMyAdmin to get the IP address. Take my solution on this with a grain of salt. phpMyAdmin is able to get the server IP somehow, so I definitely missed something on this.
I spent hours Googling solutions and dealing with issues getting Wordpress working. As a first time user of Docker, there were many layers to this problem that I was not familiar with handling with Docker. All cortisol aside, it was a very fun learning experience.
To recap, we chose Docker because we had separate dev environments and we wanted consistency in our workflow. We had a Dev server with PHP 5.X and MySQL 5.X. We wanted to make sure every developer had the same versions of PHP, APACHE, MySQL, and that the MySQL databases had the same root username/password. Since we were migrating the database using the WP Migrate DB, paths and hosts should be the same as well. Our solution does the following:
- Work with existing Wordpress directory
- No file permission issues so that we can upload plugins and images
- Automate the db syncing process as much as possible. Drop a SQL file into a folder and when you create the docker MySQL database, it will already be populated with that data.
- Needs phpMyAdmin because MySQL is easier with some sort of GUI.
Let's get started!
Create a docker-compose.yml file in the root folder as such:
apache: build: ./resources/apache # Inside resources/apache, there is a Dockerfile ports: - "8080:80" # Map port 8080 to port 80 on Apache links: - mysql # Link MySQL volumes: - ./wordpress:/var/www/html # Our wordpress folder will be mounted as /var/www/html mysql: build: ./resources/mysql # Inside resources/mysql, there is a Dockerfile volumes: - ./resources/mysql:/docker-entrypoint-initdb.d # Mount resources/mysql into docker-entrypoint-init.d. Any SQL files inside of resources/mysql will be imported into Docker MySQL automatically environment: MYSQL_DATABASE: wordpress # Database wordpress MYSQL_ROOT_PASSWORD: root # Database password root phpmyadmin: image: corbinu/docker-phpmyadmin # phpMyAdmin image ports: - "8081:80" # Map prot 8081 to port 80 links: - mysql # Link MySQL environment: MYSQL_USERNAME: root # MySQL username is root
Create resources/apache and resources/mysql. Inside resources/apache, add a Dockerfile:
FROM php:5.6-apache #Use PHP 5.6 Apache image RUN docker-php-ext-install mysqli # Install MySQL extension into PHP # Set user 1000 and group staff to www-data, enables write permission. # Helps us avoid Wordpress permission issues # https://github.com/boot2docker/boot2docker/issues/581#issuecomment-114804894 RUN usermod -u 1000 www-data RUN usermod -G staff www-data
Inside resources/mysql, add a Dockerfile
FROM mysql:latest # Use the latest MySQL image # Copy the database initialize script: # Contents of /docker-entrypoint-initdb.d are run on mysqld startup. Any SQL files inside resources/mysql will be automatically imported. ADD ./ /docker-entrypoint-initdb.d/ # Default values for passwords and database name. Can be overridden on docker run ENV MYSQL_DATABASE=wordpress # MySQL database ENV MYSQL_ROOT_USER=root # MySQL user ENV MYSQL_ROOT_PASSWORD=root # MySQL password
You should now drop your SQL export into resources/mysql. I like to call mine wordpress-starter.sql, so the full path would be resources/mysql/wordpress-starter.sql.
Launch 'Docker Quickstart Terminal'. Note the IP address given to you. What I like to do is edit my hosts file (
sudo nano /etc/hosts) and add the following:
#<dockerip> <hostname> 192.168.99.100 mywordpresssite.dev
docker-compose up -d.
Now visit mywordpresssite.dev:8081. This will bring you to a phpMyAdmin page. Login as root/root and on the top, look for where it says Server: 172.17.0.2:3306 or something similar. Copy the IP and port. This is your DB Host. Edit your wordpress/wp-config.php and paste this in as your DB_HOST:
/** MySQL hostname */ define('DB_HOST', '172.17.0.2:33306');
NOTE: I'm still looking for a better way to do handle this since the MySQL IP can change. If you know of a solution, leave a message in the comments.
Finally, visit http://mywordpresssite.dev:8080. You should see your Wordpress site. That's it, congrats! This solution took me a few hours to figure out and this information was scattered across several Github issues and Stack Overflow questions. I hope it proves useful to someone.