DEV Community

Hosting WordPress over HTTPS with Docker

Forest Hoffman on September 29, 2017

UPDATE 10/13/2020: Hello! Forest from the future here! I no longer use this setup. And, I do not intend to keep it up to date. Since I no longer m...
Collapse
 
caroga profile image
Roberto Gardenier

Hi, thank you for taking the time to create this write-up. It captures what I want to achieve.

A few questions are still keeping me away from understanding the entire picture so hopefully you could shed some light on this:

  • When focusing on the "The WordPress Containers" I think I might be missing some configuration, e.g. the nginx.conf inside the container named "nginx-wordpress". Does this mean you run the nginx container as is? Or is it using the same nginx.conf as the proxy?

  • The container named "wp" refers to a Dockerfile "Dockerfile-wp" which is not on display, am I correct?
    Also, I think I might be missing the reason behind the volume "- ./wordpress:/var/www/html" as there is a container to provide this data? Or is this for any additional files being uploaded which will not be kept inside the data-container?

Is this setup available on github somewhere?

Thank you very much!

Collapse
 
foresthoffman profile image
Forest Hoffman

Hi Roberto, thanks for taking the time to read it!

When focusing on the "The WordPress Containers" I think I might be missing some configuration, e.g. the nginx.conf inside the container named "nginx-wordpress". Does this mean you run the nginx container as is? Or is it using the same nginx.conf as the proxy?

No, the nginx-wordpress container has a separate configuration file from the nginx-proxy container. The nginx.conf file for the nginx-wordpress container is a run-of-the-mill configuration file. I believe mine is a slightly modified version of the default file that is created when you install Nginx on a normal machine. The key parts are the user and include statements. I'll add the configuration file to the write-up.

The container named "wp" refers to a Dockerfile "Dockerfile-wp" which is not on display, am I correct?

Ah yes, my apologies. I hadn't caught that. I believe the reason I overlooked it was, the Dockerfile ("Dockerfile-wp") runs some additional commands for debugging and such. I like to have a non-admin user and WP-CLI installed so that I can run some batch commands, should the need arise. The Dockerfile itself isn't crucial and the setup will work just as well if the build block in the Compose file were removed. I'll update that in the write-up.

Also, I think I might be missing the reason behind the volume "- ./wordpress:/var/www/html" as there is a container to provide this data? Or is this for any additional files being uploaded which will not be kept inside the data-container?

The reason that the wordpress directory exists on the host machine is to maintain the state of the WordPress docker container should it shutdown (this also goes for the mysql directory).

I would assume, correct me if i'm wrong, that the confusing part is the fact that the volume is mounted on both the wordpress and nginx containers. Nginx needs access the file structure that it is hosting, which happens to the same file structure that WordPress is being run on. Only mounting the wordpress directory to the WordPress container would be useless, since WordPress is about as interesting as a pet rock without a web server. On the other hand, only mounting the wordpress directory to the Nginx container would also be useless, as requests to the WordPress container wouldn't do anything.

Is this setup available on github somewhere?

No, I don't currently have anything up on GitHub regarding this. I built the write-up from what I have on my live server, so I took each piece and removed/replaced sensitive data with placeholders. For example, the MySQL password. Therefore, I don't have an anonymized version.

I'll make a reply when i've updated the write-up.

Thank you for your patience!

Collapse
 
caroga profile image
Roberto Gardenier • Edited

So, I've read your feedback, thanks for this!

I would assume, correct me if i'm wrong, that the confusing part is the fact that the volume is mounted on both the wordpress and nginx containers...

Thank you for explaining this, but this was actually not my confusion. I am confused about what the directory would actually hold.

The reason that the wordpress directory exists on the host machine is to maintain the state of the WordPress docker container should it shutdown (this also goes for the mysql directory).

Would this mean that the wordpress directory on the host machine already contains files ? Or would the modified / uploaded files be placed in there?

As for the rest of your feedback, thank you for clarifying. I will get to work with this in the next few days so I'll let you know how far it gets me.

Thank you!

Thread Thread
 
foresthoffman profile image
Forest Hoffman

The wordpress volume on the host machine holds the core WordPress files for the WordPress container (wp-config.php, wp-content/, wp-admin, etc.). Those files initially come from the WordPress container itself, when it's built. Since the wordpress volume is mounted to the container, from the host, you can do whatever you want with the files and they will propagate over to the container.

Collapse
 
foresthoffman profile image
Forest Hoffman

I've added the Nginx configuration file above, and removed the build block from the docker-compose.yml file for the WordPress containers.

Thanks again!

Collapse
 
caroga profile image
Roberto Gardenier

Hi Forest, thank you for replying so fast already!
I will be taking a look at this tomorrow as it currently is 23.20 where I live.
By the looks of it you have covered the most part I guess. You will hear from me tomorrow.
Good day/night or whatever applies to your timezone.

Cheers.

Thread Thread
 
foresthoffman profile image
Forest Hoffman

Oh cool, i'm on PST, so waaaay behind ya.

Collapse
 
cduv profile image
DUVERGIER Claude

I see server block unconditionally redirects HTTP traffic to HTTPS: So how does the Let's Encrypt server checks the ACME challenge (I was under the impression ACME checks are performed over HTTP, not over HTTPS)?

Collapse
 
foresthoffman profile image
Forest Hoffman • Edited

From my understanding they are performed over HTTP, yes. That's the reason that the redirection block and SSL blocks are commented out in step 3 of the Installing SSL Certificates with Certbot section.

Thanks!

Collapse
 
cduv profile image
DUVERGIER Claude

Right, but I don't see where this "force-all-HTTP-traffic-to-HTTPS part gets disabled/commented when certificate renewal occurs.

When I configure certificate on a "force HTTPS" Nginx configuration, I have the following in HTTP server block:

location ^~ /.well-known/acme-challenge/ {
    # No HTTP authentication
    allow all;

    # Set correct content type. According to this:
    # https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
    # Current specification requires "text/plain" or no content header at all.
    # It seems that "text/plain" is a safe option.
    default_type "text/plain";
}
location = /.well-known/acme-challenge/ {
    return 404;
}

# Redirect the rest of HTTP traffic to HTTPS:
location / {
    return 301 https://$host$request_uri;
    access_log off;
}

Thus ACME challenge gets served over HTTP, and the other requests are redirected to HTTPS.

Thread Thread
 
foresthoffman profile image
Forest Hoffman

Oh, interesting. I didn't know this was a potential issue. Thankfully, I've got quite a while before my certs need renewing. Thank you for bringing this to my attention!

Thread Thread
 
cduv profile image
DUVERGIER Claude

You're welcome :)

Thread Thread
 
foresthoffman profile image
Forest Hoffman

Updated! Thank you again. :)

Collapse
 
lionpants profile image
lionpants

Where is the image wordpress-prod:4.8.1-php5.6-fpm located?

I can't seem to pull it and if I use the regular Wordpress docker container, the container tries to listen on port 80 by default which causes conflicts with the proxy.

Collapse
 
foresthoffman profile image
Forest Hoffman

Howdy!

I'm certain that this is a custom docker container that I built using wordpress:4.8.1-php5.6-fpm. The custom stuff that I added was just personal preference. The 4.8.1-php5.6-fpm version of the official WordPress docker container is no longer available. At a glance, I believe you'll want 4.9.1-php-5.6-fpm.

i.e. The following should work.

# docker-compose.yml
...
image: wordpress:4.9.1-php-5.6-fpm
...

That said, are you using an Nginx server to support your WordPress container, as I am? If that's the case, make sure that you're using the *-fpm variety, or else the default Apache server that comes with the run-of-the-mill WordPress container will try to take over. That could be the cause of the port 80 conflict with the proxy.

Let me know if that helps.

Collapse
 
matts_bytes profile image
MWK

I had a few bugs with this setup, and would not recommend it for most users. Since there are now more mature tools for automating Wordpress installation/upkeep, I instead recommend easyengine.io.

It does virtually the same thing as this, but is much more automated and functional out of the box, easier to install and maintain, and it has a functioning nginx page/asset caching layer already configured (this does not).

Important thing to note for this Hoffman's config here: It has a top layer "https" proxy, and a proxy just below it that is part of the Wordpress "group" in that docker compose file. The Wordpress group needs to be started BEFORE the "https" group, and they need to be in separate directories as separate docker compose files.
dev-to-uploads.s3.amazonaws.com/i/...

Off the top of my head, here are two important modifications needed for smooth operation of this setup:
1: An altered startup.sh (the given one does NOT work):
gist.github.com/mkrupczak3/b928644...

2: Fix the crontab for latest versions of Certbot:
gist.github.com/mkrupczak3/f6f2765...

There are some others here that I'm forgetting, but anyways, have fun finding them! If you're new to using Docker or Docker compose, this is a decent project to get you started playing with these tools, but I would recommend total newcomers shy away from this in favor of more simple/sane projects.

Collapse
 
foresthoffman profile image
Forest Hoffman

Thanks for the comment!

This article over three years old, so I agree that it's not even close to a standard solution. I had a very personal setup that I strove to keep as bare bones as possible, using docker as my only automation tool. I personally haven't used this setup in roughly two years (I can't remember the exact date that I abandoned it).


Three years later, this article still gets views and comments. So unfortunately there are still folks that are doomed to work with legacy versions of WordPress and need a legacy solution. If this does it for you, I'm happy to have helped. If not, I wish you the best of luck!

Gif of Simon Pegg Winking

Collapse
 
nicoes profile image
Nico Eshuis • Edited

@Forest Hoffman, there seems to be a subtle difference between the code here and on your own site.
It's regarding the rule that denies access to .htaccess in de nginx/wordpress.conf.
It just a difference of a backward slash that's lacking on the example on your own site (you don't have comments there so I thought I post it here). I thought it would be worth pointing out because it took me a couple of hours since all I got was a 403 status on everything.

Collapse
 
nicoes profile image
Nico Eshuis

Furthermore I really like the set-up!

Collapse
 
foresthoffman profile image
Forest Hoffman

Well thank you very much! I'm glad you got it working, but I am sorry to hear about that little hiccup. I've been quite busy the last few months, with some serious (in a good way) life changes. Thank you for bringing this to my attention!

Collapse
 
mani1soni profile image
Manish Soni • Edited

Hi,
While running the setup, i'm getting following error in "nginx-proxy" container.

" open() "/etc/letsencrypt/options-ssl-nginx.conf" failed (2: No such file or directory) in /etc/nginx/nginx.conf:25
nginx: [emerg] open() "/etc/letsencrypt/options-ssl-nginx.conf" failed (2: No such file or directory) in /etc/nginx/nginx.conf:25
Saving debug log to /var/log/letsencrypt/letsencrypt.log ".

My folder structure is below like this---->

proxy /
crontab docker-compose.yml Dockerfile etc nginx.conf startup.sh

wordpress-nginx/
docker-compose.yml logs mysql nginx nginx.conf wordpress

and my "nginx-wordpress" container gives following error.

" /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: error: /etc/nginx/conf.d/default.conf is not a file or does not exist"

can you help.
Thanks

Collapse
 
foresthoffman profile image
Forest Hoffman

Howdy!

I believe this is an issue coming from the certbot tool, which is executed by the proxy/startup.sh script. You'll want to make sure that your nginx-proxy is accessible from outside your network. As the certbot tool will attempt to verify that the domain you've listed is actually owned by you. If your DNS provider is not already pointing to your domain, where the nginx-proxy is accessible, that would prevent the certifications from being verified.

If your domain is already correctly pointing to where your proxy will be running, you can try firing up the nginx-proxy without the startup.sh script. You'll want to comment-out the proxy/docker-compose.yml line that runs the script on docker startup (i.e. command: bash -c "startup.sh"). This should allow you to run docker-compose up on the proxy without it immediately crashing. From there, you can connect to the container and attempt to run the certbot commands manually.

Hopefully that will give you a better idea of what's going on. Best of luck! :)

Collapse
 
mani1soni profile image
Manish Soni

Thanks,
I'll try with that process and let you know.

Collapse
 
victorrims68524 profile image
Rimsha Victor Gill

Thank you for your kind words! I'm delighted that you were able to resolve the issue.
Hosting WordPress over HTTPS with Docker provides a secure and scalable solution, leveraging containerization for easier management and adding an extra layer of encryption for data protection.

Collapse
 
digital_hub profile image
hub

many thanks for posting this.☺

and for sharing your experience, ideas and thoghts

Thank you for the supporting the community here: i like your ideas: Great thoughts: thanks for all you do and share here.
keep it up - we look forward to see more support for the upcoming WordPress Version 5.9

with all the great features like
Full Site Editing (FSE)
Query Loop
Block-Theming
Gutenberg etc. etx.

Great things and enhancements ahead. The global WordPress-Community is waiting for this. And is curious about some news that cover all the good news. 🙂

see:
wptavern.com/query-loop-the-ins-an...
wptavern.com/wordpress-5-9-beta-1-...

look forward to hear from you - regards

Collapse
 
asfo profile image
Asfo

Hope you could upload this to GitHub :)

Collapse
 
foresthoffman profile image
Forest Hoffman

Hi there! Thank you for your interest. I've been quite busy the last few months with some big life changes.

This is my reasoning with regard to GitHub:

No, I don't currently have anything up on GitHub regarding this. I built the write-up from what I have on my live server, so I took each piece and removed/replaced sensitive data with placeholders. For example, the MySQL password. Therefore, I don't have an anonymized version.

In the future, perhaps i'll have time to anonymize the files that I do have and create a proper repository, but I don't expect that to happen soon.

Take care! :)

Collapse
 
x0rzkov profile image
x0rzkov

Hi guys,

Is there any repository on github with the full content of this tutorial ?

Cheers,
X.

Collapse
 
teslowa_pl profile image
TeSlowa

Hello

I want to install other software next to this using a docker ? It is possible ?

Collapse
 
foresthoffman profile image
Forest Hoffman • Edited

Hi TeSlowa,

Yes, that is absolutely possible. All Docker containers, like the ones I mention in the post, are self-contained. Anything installed to a container stays in the container. That keeps your host machine from being cluttered.

Cheers