DEV Community

Jacob Korsgaard
Jacob Korsgaard

Posted on

Playing with Docker on Unraid from Windows 10

I've recently setup an Unraid server in my house and wanted to use the opportunity to learn a bit about Docker by developing a simple web app and deploy it to the server.

I'm writing this series to leave a paper trail for other people to follow since I ran into a number of issues.

I am by no means a docker expert. This is all from the point of view of a docker novice.

First a few basic details about my setup:

  • It's March 2021
  • Development PC is a Windows 10 version: 10.0.19042.867
  • Unraid is version: 6.9.1
  • Docker Engine is version: 20.10.5
  • I've installed WSL2

Here are some links to get the basics up and running:

The web app I'm building has a frontend (Angular/Ionic) and a backend (NodeJS). I'm not really going to go into those things as this is mostly about just getting docker working on Unraid.


Creating the Docker images and containers for my App

Initially I was going to use PHP for the server - because it's what I already had - but I found this excellent:

NGINX with Docker and Node.js — a Beginner’s guide

The end product of this guide is an NGINX container that serves as a reverse proxy for a Node.js server.

I didn't know what a reverse proxy was, but essentially it lets you access another service through the endpoint of NGINX. You can configure NGINX to pass your requests to another server and ferry the response back. This can be helpful if you want to hide the actual location of the other server. NGINX can also take care of all the HTTPS security stuff for your reversed proxied server.

This guide doesn't add a frontend so I thought I'd try to do that myself and followed the documentation from NGINX: NGINX Docs | Serving Static Content

Setting up the NGINX docker container

It only requires 2 files to setup NGINX in a container

  • Dockerfile the instructions to create the image.
  • default.conf the configuration of the server.

That's about as easy as anyone could hope for.

The Dockerfile literally just splats the configuration onto the server and you're done.

FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
Enter fullscreen mode Exit fullscreen mode

Now my default.conf looks like this:

server {
  root /data;

  location /media {
    rewrite ^/media(.*)$ $1 break;
    root /media;
  }

  location /nodeserver {
    rewrite ^/nodeserver(.*)$ /$1 break;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_pass http://nodeserver:5000;
  }
}
Enter fullscreen mode Exit fullscreen mode

This is somewhat similar to Ashwin's guide, but I'll try to explain what I'm doing here.

First up root /data; is the root directory used to try to find the static content. I'm expecting the container to be able to find some HTML (particularly index.html) in the /data folder. I'll accomplish this later by mounting a folder on my system to the /data folder in the container.

The location /media block I use to serve some media files from another folder separate from the /data folder. Whenever someone requests a url that starts with /media/, then we serve from root /media; instead of the default root.

I did this without the rewrite line first, but then my requests would all be prefixed with /media so when I request http://localhost/media/myfile.mp4 NGINX would try to serve the file /media/media/myfile.mp4. To remove the first /media I used this rewrite rule. A solution I found here: serverfault | how to remove location block from $uri in nginx configuration?

Finally, there is the /nodeserver location, this is my access to the backend. Here I setup the reverse proxy as described in Ashwin's guide. I use the same rewrite rule here to remove the prefix from the requests forwarded to the backend. It's really crucial to note the / prefix in /$1, this won't work with just $1. I found the solution to that here

Node.JS container setup

I used the same approach as in Ashwin's guide.

Here is the Dockerfile I used to create my node server:

FROM node:alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5000
CMD ["node", "index.js"]
Enter fullscreen mode Exit fullscreen mode

docker-compose for local deployment

I found Docker quite cumbersome before I made it to the docker-compose stage. It does make it a lot easier.

For a local deployment of this app, I need to spin up my two containers together and mount in a /data and a /media folder.

docker-compose.yml for that looks something like this:

version: "3.8"
services:
  nodeserver:
    build:
      # home-video-server has the nodeserver node.js DockerFile
      context: ./home-video-server
  nginx:
    restart: always
    build:
      # home-server-nginx has the NGINX DockerFile
      context: ./home-server-nginx
    ports:
      - "81:80"
    volumes:
      # Map the subfolder home-video/www to the /data folder
      - ./home-video/www:/data
      # and put my videos in the media folder
      - c:\Users\jacob\videos:/media
Enter fullscreen mode Exit fullscreen mode

You can use docker-compose up --build to update the images and restart the containers.

In the default.conf for the NGINX server, you may have noticed that it refers to nodeserver by http://nodeserver:5000/ this kind of reference is only possible because we used docker compose with both containers. It's facilitated by a docker network that's created automatically. See Docker Compose Documentation on Networking.


Next time I'll explain how I managed to deploy the containers to my Unraid server using SSH.

Top comments (0)