├── .gitignore ├── cron.conf ├── supervisord.conf ├── docker-entrypoint.sh ├── virtual-host.conf ├── .env ├── README.md ├── docker-compose.yml ├── nginx.conf ├── Dockerfile └── wp-config.php /.gitignore: -------------------------------------------------------------------------------- 1 | wp 2 | db 3 | content 4 | redis 5 | -------------------------------------------------------------------------------- /cron.conf: -------------------------------------------------------------------------------- 1 | # Cron configuration file, set to run WordPress cron once every minute 2 | * * * * * php /usr/src/wordpress/wp-cron.php 3 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | loglevel=debug 4 | logfile=/var/log/supervisor/supervisord.log 5 | pidfile=/var/run/supervisord.pid 6 | childlogdir=/var/log/supervisor 7 | 8 | [program:nginx] 9 | command=nginx -g "daemon off;" 10 | redirect_stderr=true 11 | 12 | [program:php-fpm] 13 | command=php-fpm 14 | redirect_stderr=true 15 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e # terminate on errors 4 | 5 | function test_mysql { 6 | mysqladmin -h "${WP_DB_HOST}" ping 7 | } 8 | 9 | function test_redis { 10 | redis-cli -h "${WP_REDIS_HOST}" PING 11 | } 12 | 13 | until (test_mysql && test_redis); do 14 | >&2 echo "Dependencies unavailable - sleeping." 15 | sleep 3 16 | done 17 | 18 | >&2 echo "Dependencies are up - executing command." 19 | 20 | exec "$@" 21 | -------------------------------------------------------------------------------- /virtual-host.conf: -------------------------------------------------------------------------------- 1 | server { 2 | server_name _; 3 | listen 80 default_server; 4 | 5 | root /usr/src/wordpress; 6 | index index.php index.html; 7 | 8 | access_log /dev/stdout; 9 | error_log /dev/stdout info; 10 | 11 | location /content { 12 | root /var/www; 13 | expires 1M; 14 | access_log off; 15 | add_header Cache-Control "public"; 16 | } 17 | 18 | location / { 19 | try_files $uri $uri/ /index.php?$args; 20 | } 21 | 22 | location ~ \.php$ { 23 | include fastcgi_params; 24 | fastcgi_pass 127.0.0.1:9000; 25 | fastcgi_index index.php; 26 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | DOCKER_ENV=development 2 | 3 | # Most of these are being read by wp-config.php 4 | WP_CONTENT_DIR=/var/www/content 5 | WP_CONTENT_DIRNAME=content 6 | DISABLE_WP_CRON=true 7 | WP_REDIS_HOST=redis 8 | WP_DB_NAME=wp 9 | WP_DB_USER=wp 10 | WP_DB_PASSWORD=wp 11 | WP_DB_HOST=mysql 12 | WP_TABLE_PREFIX=wp_ 13 | WP_SITEURL=http://localhost:8080 14 | WP_DEBUG=true 15 | WP_CACHE_KEY_SALT=my-site- 16 | FS_METHOD=direct 17 | 18 | # Don't forget to update these: https://api.wordpress.org/secret-key/1.1/salt/ 19 | AUTH_KEY=your_auth_key 20 | SECURE_AUTH_KEY=your_secure_auth_key 21 | LOGGED_IN_KEY=your_logged_in_key 22 | NONCE_KEY=your_nonce_key 23 | AUTH_SALT=your_auth_salt 24 | SECURE_AUTH_SALT=your_secure_auth_salt 25 | LOGGED_IN_SALT=your_logged_in_salt 26 | NONCE_SALT=your_nonce_salt 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress developer's intro to Docker 2 | 3 | In order for this build this image properly, you need to download WordPress (or take an existing install) and copy `wp-content` into this directory, renaming it to just `content` - discard/ignore the WordPress core as it's being downloaded within the image itself. 4 | 5 | Next, create two directories named `db` and `redis` and leave them empty. They will be used to store MySQL and Redis database files. 6 | 7 | Finally, to build the image, run: 8 | ``` 9 | $ docker-compose build 10 | ``` 11 | 12 | And then to run the container, use this command: 13 | ``` 14 | $ docker-compose up 15 | ``` 16 | (cancel these with `CTRL + C`) 17 | 18 | To test it out, open your browser, and navigate to `http://localhost:8080` (or whatever you have set in the `.env` file) 19 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | wordpress: 4 | build: . 5 | volumes: 6 | - ./content:/var/www/content 7 | env_file: .env 8 | ports: 9 | - "8080:80" 10 | links: 11 | - mysql 12 | - redis 13 | cron: 14 | build: . 15 | command: crond -f -l 6 -L /dev/stdout 16 | volumes: 17 | - ./content:/var/www/content 18 | env_file: .env 19 | links: 20 | - mysql 21 | - redis 22 | mysql: 23 | image: mariadb:5.5 24 | volumes: 25 | - ./db:/var/lib/mysql 26 | environment: 27 | MYSQL_ROOT_PASSWORD: wp 28 | MYSQL_DATABASE: wp 29 | MYSQL_USER: wp 30 | MYSQL_PASSWORD: wp 31 | redis: 32 | image: redis:3.2.0-alpine 33 | command: redis-server --appendonly yes 34 | volumes: 35 | - ./redis:/data 36 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | include /etc/nginx/mime.types; 13 | default_type application/octet-stream; 14 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 15 | '$status $body_bytes_sent "$http_referer" ' 16 | '"$http_user_agent" "$http_x_forwarded_for"'; 17 | access_log /var/log/nginx/access.log main; 18 | sendfile on; 19 | keepalive_timeout 65; 20 | client_max_body_size 10m; 21 | 22 | gzip on; 23 | gzip_buffers 16 8k; 24 | gzip_comp_level 9; 25 | gzip_http_version 1.0; 26 | gzip_min_length 0; 27 | gzip_types text/plain text/css image/x-icon image/svg+xml image/png image/jpg image/jpeg text/js text/php application/javascript application/x-javascript; 28 | gzip_vary on; 29 | gzip_proxied expired no-cache no-store private auth; 30 | gzip_disable "MSIE [1-6]\."; 31 | 32 | include /etc/nginx/conf.d/*.conf; 33 | } 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.0.6-fpm-alpine 2 | MAINTAINER Tomaz Zaman 3 | 4 | # We need these system-level scritps to run WordPress successfully 5 | RUN apk add --no-cache nginx mysql-client supervisor curl \ 6 | bash redis imagemagick-dev 7 | 8 | # As per image documentation, this is how we install PHP modules 9 | RUN docker-php-ext-install -j$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) \ 10 | iconv gd mbstring fileinfo curl xmlreader xmlwriter spl ftp mysqli opcache 11 | 12 | # Install imagemagick for PHP 13 | RUN apk add --no-cache libtool build-base autoconf \ 14 | && pecl install imagick \ 15 | && docker-php-ext-enable imagick \ 16 | && apk del libtool build-base autoconf 17 | 18 | # Create a user called "deployer" without a password and belonging 19 | # to the same group as php-fpm and nginx belong to 20 | RUN adduser -D deployer -s /bin/bash -G www-data 21 | 22 | # Set working directory to wp-content, which is a mounted volume 23 | VOLUME /var/www/content 24 | WORKDIR /var/www/content 25 | 26 | # Environment variables that make the reuse easier 27 | ENV WP_ROOT /usr/src/wordpress 28 | ENV WP_VERSION 4.5.2 29 | ENV WP_SHA1 bab94003a5d2285f6ae76407e7b1bbb75382c36e 30 | ENV WP_DOWNLOAD_URL https://wordpress.org/wordpress-$WP_VERSION.tar.gz 31 | 32 | # Download WP and extract it to /usr/src/wordpress 33 | RUN curl -o wordpress.tar.gz -SL $WP_DOWNLOAD_URL \ 34 | && echo "$WP_SHA1 *wordpress.tar.gz" | sha1sum -c - \ 35 | && tar -xzf wordpress.tar.gz -C /usr/src/ \ 36 | && rm wordpress.tar.gz 37 | 38 | # Copy our cron configuration and set proper permissions 39 | COPY cron.conf /etc/crontabs/deployer 40 | RUN chmod 600 /etc/crontabs/deployer 41 | 42 | # Install WP-CLI (for convenience) 43 | RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \ 44 | && chmod +x wp-cli.phar \ 45 | && mv wp-cli.phar /usr/local/bin/wp 46 | 47 | # Copy over our custom Nginx configuration and log to stderr/stdout 48 | COPY nginx.conf /etc/nginx/nginx.conf 49 | COPY virtual-host.conf /etc/nginx/conf.d/ 50 | RUN ln -sf /dev/stdout /var/log/nginx/access.log \ 51 | && ln -sf /dev/stderr /var/log/nginx/error.log \ 52 | && chown -R www-data:www-data /var/lib/nginx 53 | 54 | # Copy our configuration and set proper permissions 55 | COPY wp-config.php $WP_ROOT 56 | RUN chown -R deployer:www-data $WP_ROOT \ 57 | && chmod 640 $WP_ROOT/wp-config.php 58 | 59 | RUN mkdir -p /var/www/content/uploads \ 60 | && chown -R www-data:www-data /var/www/content/uploads 61 | 62 | # Copy supervisor configuration for both processes 63 | RUN mkdir -p /var/log/supervisor 64 | COPY supervisord.conf /etc/supervisord.conf 65 | 66 | # Copy and prepare the entrypoint 67 | COPY docker-entrypoint.sh / 68 | RUN chmod +x /docker-entrypoint.sh 69 | ENTRYPOINT [ "/docker-entrypoint.sh" ] 70 | 71 | CMD [ "/usr/bin/supervisord", "-c", "/etc/supervisord.conf" ] 72 | -------------------------------------------------------------------------------- /wp-config.php: -------------------------------------------------------------------------------- 1 |