├── .gitignore ├── Dockerfile ├── README.md ├── nginx-site.conf ├── start.sh └── supervisord.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | MAINTAINER Eugene Ware 3 | RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list 4 | RUN apt-get update 5 | RUN apt-get -y upgrade 6 | 7 | # Keep upstart from complaining 8 | RUN dpkg-divert --local --rename --add /sbin/initctl 9 | RUN ln -sf /bin/true /sbin/initctl 10 | RUN mkdir /var/run/sshd 11 | 12 | # Basic Requirements 13 | RUN apt-get -y install memcached mysql-server mysql-client nginx php5-fpm php5-mysql php-apc pwgen python-setuptools curl git unzip openssh-server openssl 14 | 15 | # Wordpress Requirements 16 | RUN apt-get -y install php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-memcached php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl 17 | 18 | # mysql config 19 | RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf 20 | 21 | # nginx config 22 | RUN sed -i -e"s/keepalive_timeout\s*65/keepalive_timeout 2/" /etc/nginx/nginx.conf 23 | RUN sed -i -e"s/keepalive_timeout 2/keepalive_timeout 2;\n\tclient_max_body_size 100m/" /etc/nginx/nginx.conf 24 | RUN echo "daemon off;" >> /etc/nginx/nginx.conf 25 | 26 | # php-fpm config 27 | RUN sed -i -e "s/upload_max_filesize\s*=\s*2M/upload_max_filesize = 100M/g" /etc/php5/fpm/php.ini 28 | RUN sed -i -e "s/post_max_size\s*=\s*8M/post_max_size = 100M/g" /etc/php5/fpm/php.ini 29 | RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf 30 | RUN find /etc/php5/cli/conf.d/ -name "*.ini" -exec sed -i -re 's/^(\s*)#(.*)/\1;\2/g' {} \; 31 | 32 | # nginx site conf 33 | ADD ./nginx-site.conf /etc/nginx/sites-available/default 34 | 35 | # Supervisor Config 36 | RUN /usr/bin/easy_install supervisor 37 | ADD ./supervisord.conf /etc/supervisord.conf 38 | 39 | #Add system user for Wordpress 40 | RUN useradd -m -d /home/wordpress -p $(openssl passwd -1 'temp') -G sudo -s /bin/bash wordpress 41 | RUN ln -s /usr/share/nginx/www /home/wordpress/www 42 | 43 | # SSH security, turn off root login 44 | RUN sed -i -e "s/PermitRootLogin\syes/PermitRootLogin no/g" /etc/ssh/sshd_config 45 | 46 | # Install Wordpress 47 | ADD http://wordpress.org/latest.tar.gz /usr/share/nginx/latest.tar.gz 48 | RUN cd /usr/share/nginx/ && tar xvf latest.tar.gz && rm latest.tar.gz 49 | RUN mv /usr/share/nginx/www/5* /usr/share/nginx/wordpress 50 | RUN rm -rf /usr/share/nginx/www 51 | RUN mv /usr/share/nginx/wordpress /usr/share/nginx/www 52 | RUN chown -R wordpress:www-data /usr/share/nginx/www 53 | RUN chmod -R 775 /usr/share/nginx/www 54 | 55 | # Wordpress Initialization and Startup Script 56 | ADD ./start.sh /start.sh 57 | RUN chmod 755 /start.sh 58 | 59 | # private expose 60 | EXPOSE 80 61 | EXPOSE 22 62 | 63 | CMD ["/bin/bash", "/start.sh"] 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-wordpress-nginx-ssh 2 | 3 | A Dockerfile that installs the latest wordpress, nginx, php-apc, php-fpm and openssh. 4 | Now with memcached caching straight from NGiNX! 5 | 6 | This is a modified fork from [eugeneware](https://github.com/eugeneware/docker-wordpress-nginx). All credits should go to him. 7 | 8 | ## Installation 9 | 10 | $ git clone https://github.com/oskarhane/docker-wordpress-nginx-ssh.git 11 | $ cd docker-wordpress-nginx-ssh 12 | $ sudo docker build -t="docker-wordpress-nginx-ssh" . 13 | 14 | ## Usage 15 | 16 | To spawn a new instance of wordpress: 17 | 18 | $ sudo docker run -p 80 -p 22 -d -t docker-wordpress-nginx-ssh 19 | 20 | You'll see an ID output like: `d404cc2fa27b` 21 | 22 | Use this ID to check the port it's on: 23 | 24 | $ sudo docker port d404cc2fa27b 80 # Make sure to change the ID to yours! 25 | 26 | This command returns the container ID, which you can use to find the external port you can use to access Wordpress from your host machine: 27 | 28 | $ docker port 80 29 | 30 | You can the visit the following URL in a browser on your host machine to get started: 31 | 32 | http://127.0.0.1: 33 | 34 | To enable memcached caching straight from NGiNX, goto WP-FFPC settings page and press the save button. Thats it. 35 | 36 | 37 | To get the SSH user `wordpress`'s password so you can login and edit files, check the top of the docker container logs for it. 38 | 39 | $ docker logs 40 | -------------------------------------------------------------------------------- /nginx-site.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; ## listen for ipv4; this line is default and implied 3 | listen [::]:80 default ipv6only=on; ## listen for ipv6 4 | 5 | charset UTF-8; 6 | root /usr/share/nginx/www; 7 | index index.php index.html index.htm; 8 | 9 | server_name localhost; 10 | 11 | location / { 12 | try_files $uri $uri/ @memcached; 13 | } 14 | 15 | location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { 16 | expires 24h; 17 | log_not_found off; 18 | } 19 | 20 | # redirect server error pages to the static page /50x.html 21 | # 22 | error_page 500 502 503 504 /50x.html; 23 | location = /50x.html { 24 | root /usr/share/nginx/www; 25 | } 26 | 27 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 28 | # 29 | location ~ (\.php) { 30 | try_files $uri =404; 31 | fastcgi_index index.php; 32 | fastcgi_connect_timeout 10; 33 | fastcgi_send_timeout 180; 34 | fastcgi_read_timeout 180; 35 | fastcgi_buffer_size 512k; 36 | fastcgi_buffers 4 256k; 37 | fastcgi_busy_buffers_size 512k; 38 | fastcgi_temp_file_write_size 512k; 39 | fastcgi_intercept_errors on; 40 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 41 | fastcgi_keep_conn on; 42 | 43 | fastcgi_param QUERY_STRING $query_string; 44 | fastcgi_param REQUEST_METHOD $request_method; 45 | fastcgi_param CONTENT_TYPE $content_type; 46 | fastcgi_param CONTENT_LENGTH $content_length; 47 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 48 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 49 | fastcgi_param REQUEST_URI $request_uri; 50 | fastcgi_param DOCUMENT_URI $document_uri; 51 | fastcgi_param DOCUMENT_ROOT $document_root; 52 | fastcgi_param SERVER_PROTOCOL $server_protocol; 53 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 54 | fastcgi_param SERVER_SOFTWARE nginx; 55 | fastcgi_param REMOTE_ADDR $remote_addr; 56 | fastcgi_param REMOTE_PORT $remote_port; 57 | fastcgi_param SERVER_ADDR $server_addr; 58 | fastcgi_param SERVER_PORT $server_port; 59 | fastcgi_param SERVER_NAME $server_name; 60 | fastcgi_param PATH_INFO $fastcgi_path_info; 61 | fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; 62 | fastcgi_param REDIRECT_STATUS 200; 63 | 64 | # uncomment these for HTTPS usage 65 | #fastcgi_param HTTPS $https if_not_empty; 66 | #fastcgi_param SSL_PROTOCOL $ssl_protocol if_not_empty; 67 | #fastcgi_param SSL_CIPHER $ssl_cipher if_not_empty; 68 | #fastcgi_param SSL_SESSION_ID $ssl_session_id if_not_empty; 69 | #fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify if_not_empty; 70 | 71 | fastcgi_pass 127.0.0.1:9000; 72 | } 73 | 74 | # try to get result from memcached 75 | location @memcached { 76 | default_type text/html; 77 | set $memcached_key data-$scheme://$host$request_uri; 78 | set $memcached_request 1; 79 | 80 | # exceptions 81 | # avoid cache serve of POST requests 82 | if ($request_method = POST ) { 83 | set $memcached_request 0; 84 | } 85 | 86 | # avoid cache serve of wp-admin-like pages, starting with "wp-" 87 | if ( $uri ~ "/wp-" ) { 88 | set $memcached_request 0; 89 | } 90 | 91 | # avoid cache serve of any URL with query strings 92 | if ( $args ) { 93 | set $memcached_request 0; 94 | } 95 | 96 | 97 | if ($http_cookie ~* "comment_author_|wordpressuser_|wp-postpass_|wordpress_logged_in_" ) { 98 | set $memcached_request 0; 99 | } 100 | 101 | 102 | 103 | if ( $memcached_request = 1) { 104 | add_header X-Cache-Engine "WP-FFPC with memcache via nginx"; 105 | memcached_pass memcached-servers; 106 | error_page 404 = @rewrites; 107 | } 108 | 109 | if ( $memcached_request = 0) { 110 | rewrite ^ /index.php last; 111 | } 112 | } 113 | 114 | location @rewrites { 115 | add_header X-Cache-Engine "No cache"; 116 | rewrite ^ /index.php last; 117 | } 118 | 119 | } 120 | 121 | upstream memcached-servers { 122 | server 127.0.0.1:11211; 123 | } -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -f /usr/share/nginx/www/wp-config.php ]; then 3 | #mysql has to be started this way as it doesn't work to call from /etc/init.d 4 | /usr/bin/mysqld_safe & 5 | sleep 10s 6 | # Here we generate random passwords (thank you pwgen!). The first two are for mysql users, the last batch for random keys in wp-config.php 7 | WORDPRESS_DB="wordpress" 8 | MYSQL_PASSWORD=`pwgen -c -n -1 12` 9 | WORDPRESS_PASSWORD=`pwgen -c -n -1 12` 10 | SSH_PASSWORD=`pwgen -c -n -1 12` 11 | #This is so the passwords show up in logs. 12 | echo mysql root password: $MYSQL_PASSWORD 13 | echo wordpress password: $WORDPRESS_PASSWORD 14 | echo ssh password: $SSH_PASSWORD 15 | echo $MYSQL_PASSWORD > /mysql-root-pw.txt 16 | echo $WORDPRESS_PASSWORD > /wordpress-db-pw.txt 17 | 18 | #Update linux user password to the new random one 19 | usermod -p $(openssl passwd -1 $SSH_PASSWORD) wordpress 20 | 21 | sed -e "s/database_name_here/$WORDPRESS_DB/ 22 | s/username_here/$WORDPRESS_DB/ 23 | s/password_here/$WORDPRESS_PASSWORD/ 24 | /'AUTH_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 25 | /'SECURE_AUTH_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 26 | /'LOGGED_IN_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 27 | /'NONCE_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 28 | /'AUTH_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 29 | /'SECURE_AUTH_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 30 | /'LOGGED_IN_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 31 | /'NONCE_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/" /usr/share/nginx/www/wp-config-sample.php > /usr/share/nginx/www/wp-config.php 32 | 33 | # Download nginx helper plugin 34 | curl -O `curl -i -s http://wordpress.org/plugins/nginx-helper/ | egrep -o "http://downloads.wordpress.org/plugin/[^']+"` 35 | unzip nginx-helper.*.zip -d /usr/share/nginx/www/wp-content/plugins 36 | 37 | curl -O `curl -i -s http://wordpress.org/plugins/wp-ffpc/ | egrep -o "http://downloads.wordpress.org/plugin/[^']+"` 38 | unzip wp-ffpc.*.zip -d /usr/share/nginx/www/wp-content/plugins 39 | chown -R wordpress:www-data /usr/share/nginx/www/wp-content/plugins 40 | 41 | sed -i -e $"s/define('WP_DEBUG', false);/define('WP_DEBUG', false);\ndefine('WP_CACHE', true);\ndefine('FS_METHOD', 'direct');/" /usr/share/nginx/www/wp-config.php 42 | 43 | 44 | # Activate nginx plugin and set up pretty permalink structure once logged in 45 | cat << ENDL >> /usr/share/nginx/www/wp-config.php 46 | \$plugins = get_option( 'active_plugins' ); 47 | if ( count( \$plugins ) === 0 ) { 48 | require_once(ABSPATH .'/wp-admin/includes/plugin.php'); 49 | \$wp_rewrite->set_permalink_structure( '/%postname%/' ); 50 | \$pluginsToActivate = array( 'nginx-helper/nginx-helper.php' , 'wp-ffpc/wp-ffpc.php'); 51 | foreach ( \$pluginsToActivate as \$plugin ) { 52 | if ( !in_array( \$plugin, \$plugins ) ) { 53 | activate_plugin( '/usr/share/nginx/www/wp-content/plugins/' . \$plugin ); 54 | } 55 | } 56 | } 57 | ENDL 58 | 59 | chown wordpress:www-data /usr/share/nginx/www/wp-config.php 60 | 61 | mysqladmin -u root password $MYSQL_PASSWORD 62 | mysql -uroot -p$MYSQL_PASSWORD -e "CREATE DATABASE wordpress; GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY '$WORDPRESS_PASSWORD'; FLUSH PRIVILEGES;" 63 | killall mysqld 64 | fi 65 | 66 | # start all the services 67 | service memcached start 68 | /usr/local/bin/supervisord -n 69 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [unix_http_server] 2 | file=/tmp/supervisor.sock ; (the path to the socket file) 3 | 4 | [supervisord] 5 | logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log) 6 | logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB) 7 | logfile_backups=10 ; (num of main logfile rotation backups;default 10) 8 | loglevel=info ; (log level;default info; others: debug,warn,trace) 9 | pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 10 | nodaemon=false ; (start in foreground if true;default false) 11 | minfds=1024 ; (min. avail startup file descriptors;default 1024) 12 | minprocs=200 ; (min. avail process descriptors;default 200) 13 | 14 | ; the below section must remain in the config file for RPC 15 | ; (supervisorctl/web interface) to work, additional interfaces may be 16 | ; added by defining them in separate rpcinterface: sections 17 | [rpcinterface:supervisor] 18 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 19 | 20 | [supervisorctl] 21 | serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket 22 | 23 | [program:php5-fpm] 24 | command=/usr/sbin/php5-fpm -c /etc/php5/fpm 25 | 26 | [program:mysqld] 27 | command=/usr/bin/mysqld_safe 28 | 29 | [program:nginx] 30 | command=/usr/sbin/nginx 31 | 32 | [program:ssh] 33 | command=/usr/sbin/sshd -D --------------------------------------------------------------------------------