DEV Community

Cover image for Password Protect a Dockerized Nginx Server: Step by Step
Kevin Lien
Kevin Lien

Posted on

Password Protect a Dockerized Nginx Server: Step by Step

Quite often when a site is in development it can be necessary to grant access to users on a case by case basis. Having the opportunity to create custom username/password authentication is extremely useful and is usually taken care of via a web host's control panel. But in more and more circumstances, working directly with web containers is becoming the standard and you'll find yourself creating and deploying your own web server from scratch. I've found the easiest way to do that is through the official Nginx Docker container.

There are a lot of "Hello World" tutorials on how to quickly spin up a web server using Nginx but as soon as you start trying to add basic authentication in the mix it gets considerably more difficult to figure out. Surprisingly it actually isn't very complicated and once you have the initial config files and Dockerfiles created, it's a pretty quick process.

Let's start by getting the basic server launched to make sure everything is working. First thing is you need a site to serve and as it happens, I just created one for you:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Cool Site</title>
  </head>
  <body>
    <div
      style="
        display: flex;
        align-items: center;
        justify-content: center;
        height: 500px;
      "
    >
      Welcome to My Cool Site &trade;
    </div>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

Image description
(save this file as /dist/index.html)
Our site is taking advantage of all the latest in Web3 features and just needs to be hosted.

Before we debut it to the world, let's get it working in Docker Desktop. We'll be using the latest build of Nginx using the alpine official image:

FROM nginx:alpine
COPY ./dist /usr/share/nginx/html/

Enter fullscreen mode Exit fullscreen mode

Image description
(save this file as Dockerfile)
We've created our Dockerfile, now we just need to build, run and enjoy. Building is easy:

docker build -t cool-site-server-dev:latest .
Enter fullscreen mode Exit fullscreen mode

And now we run it:

docker run -dp 3000:80 --name CoolSite cool-site-server-dev
Enter fullscreen mode Exit fullscreen mode

If you visit localhost:3000 in your browser, your new site is deployed. You can now take that same image and deploy it on any container-base cloud platform like Heroku, Cloud Run, Fargate (if you want to help Bezos build another Blue Origin), etc.
Image description

Arguably the site is already stunning, but maybe you want to add some new features and run them by a client first. You don't want just anyone stumbling across the site during development so lets add some authentication to the frontend.

First thing that needs to happen is we need to create a user file for basic authentication. This will be the username/password combo that is required to visit a site. You can roll your own or just visit a site like Web 2.0 Generators and use theirs. That will generate an MD5 Hashed password that can be used in conjunction with our Nginx config to lock down the site.

Image description
In our case, a simple Username of "client" and Password of "password2022" will work. That produces the following UN/PW combination that will need to be saved as an .htpasswd file:

 client:$apr1$xu3ntfr2$.bvn2673gIlT4sxAAI0p51
Enter fullscreen mode Exit fullscreen mode

Image description
At this point we have a working site, a working container, and a username and password that we want to use. All we need now is to add the authentication. We will need to make some quick alterations to our Dockerfile to add some extra commands during build, but first, lets create a config file for our Nginx server to tell it to require authentication.

The new file we create is called nginx.conf with the following code:

worker_processes auto;

events { worker_connections 1024; }

  http {
    server {

        location / {
          root   /usr/share/nginx/html;
          index  index.html index.htm;

          auth_basic "Restricted";
          auth_basic_user_file  /etc/nginx/.htpasswd;

          include  /etc/nginx/mime.types;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description
Once that's saved, we're ready to add it to our Docker build process. We only need to add 2 lines of code to the Dockerfile. 1 line to copy in the nginx config file to the proper place in the container and the second to add the username/password files. The final Dockerfile will be:

FROM nginx:alpine
COPY ./dist /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf
COPY .htpasswd /etc/nginx/.htpasswd
Enter fullscreen mode Exit fullscreen mode

Image description
We're finally ready to deploy version 2.0 our site with the added changes and username/password authentication. We rebuild our container:

docker build -t cool-site-server-dev:latest .
Enter fullscreen mode Exit fullscreen mode

And run it:

docker run -dp 3000:80 --name CoolSite cool-site-server-dev
Enter fullscreen mode Exit fullscreen mode

And now we're met with a Sign In message:

Image description
We enter the username (client) and password (password2022) combination that we generated on the Web 2.0 Generators site and just like that, we have access to the new and improved site!

Image description
I hope that helps the next time you're developing a site and want to only grant access to a certain set of individuals.

(Shout out to Mackenzie Marco for the header image)

Top comments (3)

Collapse
 
gmcruz profile image
gmcruz • Edited

docker run --restart always --name sitmp-nginx -p 3738:80 \
-v /sitmp/index.html:/usr/share/nginx/html/index.html \
-v /sitmp/nginx.conf:/etc/nginx/nginx.conf \
-v /sitmp/.htpasswd:/etc/nginx/.htpasswd \
-d nginx:1.25.2

Make the files in /sitemp (of course wherever you want) and change as needed.

Just figured this out, it stays static if you change the index.html page; must be something with docker volumes. Not sure why, so you need the following:

docker run --restart always --name sitmp-nginx -p 3738:80 \
-v /sitmp:/usr/share/nginx/html \
-v /sitmp/nginx.conf:/etc/nginx/nginx.conf \
-v /sitmp/.htpasswd:/etc/nginx/.htpasswd \
-d nginx:1.25.2

Collapse
 
spock123 profile image
Lars Rye Jeppesen

Thank you, just what I was looking for

Collapse
 
kevinlien profile image
Kevin Lien

Glad to help!