Remote Deploy with Docker-Compose to Unraid
Tags: unraid, docker, papertrail, windows
Published: 2021-03-16 21:17:23

In my [previous post](https://dev.to/felizk/playing-with-docker-on-unraid-from-windows-10-4060) I built a couple of containers with docker-compose. Now I'd like to share how I deploy those containers to my Unraid server using SSH.

I've had two goals, from my Windows machine I'd like to:

 * Deploy my containers to Unraid
 * Iterate on the containers locally

---

# Multiple configurations with docker-compose
The first thing I tackled was figuring out how to customize my docker compose files based on the target I'm building for.

It turns out the tool for that is [Multiple Compose Files](https://docs.docker.com/compose/extends/).

By default when you run `docker-compose`, the tool read two files from the target directory `docker-compose.yml` and `docker-compose.override.yml`. These two files are effectively merged to create the configuration. The thought is you'd put the common configuration into `docker-compose.yml` and your development settings into the override.

**docker-compose.yml**
```
version: "3.8"
services:
    nodeserver:
        build:
            context: ./home-video-server
    nginx:
        restart: always
        build:
            context: ./home-server-nginx
```

**docker-compose.override.yml**
```
version: "3.8"
services:
    nodeserver:
        volumes:
            - c:\Users\jacob\videos:/media
    nginx:
        restart: always
        ports:
            - "81:80"
        volumes:
            - ./home-video/www:/data
            - c:\Users\jacob\videos:/media
```

When you want to run a command using a different configuration, what you do is you explicitly declare exactly which files to use in the configuration. I created a `docker-compose.prod.yml` with the settings for the Unraid containers.

**docker-compose.prod.yml**
```
version: "3.8"
services:
  nodeserver:
    volumes:
      - /mnt/user/kids:/media
  nginx:
    restart: always
    ports:
      - "9000:80"
    volumes:
      - /mnt/user/web:/data
      - /mnt/user/kids:/media
```  

the command I run when building for unraid is then

```
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --build
```

---

# Using Contexts to target Unraid
Now to actually send those containers to Unraid using docker-compose.

There are a number of different methods you can use, I found this nice article going over some of them: [How to deploy on remote Docker hosts with docker-compose](https://www.docker.com/blog/how-to-deploy-on-remote-docker-hosts-with-docker-compose/)

**Contexts** is the weapon of choice and it's fairly straightforward. First we have to create a context, which is a named connection string basically. Then we have to use that context in all our docker commands to make them execute on the target.

**Create a context called 'remote'**
```
docker context create remote ‐‐docker “host=ssh://user@remotemachine”
```
This command will use SSH to connect to a 'docker endpoint' (that's the --docker part). [Docker Context Documentation](https://docs.docker.com/engine/context/working-with-contexts/)

For Unraid, it'll look something like this:
```
docker context create unraid ‐‐docker “host=ssh://root@tower”
```
Our command from before now becomes the following:
```
docker-compose --context unraid -f docker-compose.yml -f docker-compose.prod.yml up --build
```

---

## SSH to Unraid (Use SSH Keys)
If you tried running this you would be asked for your root password roughly a 100 times and it's likely the job would fail anyway.

Because docker-compose executes so many commands over the SSH connection, it will need the password many times. We can't have that and will have to setup an SSH key.

Before that though: **SSH doesn't work on Unraid by default** (Access Denied error). You have to login to Unraid and give the root user a password before you can SSH. It's not enough to create a new user and give that a password, root has to have a password.

What we need to do now is generate an SSH key on our Windows 10 machine. Then copy the public part of the key to Unraid.

I used this guide to help me with SSH keys [How To Set Up SSH Keys
](https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys-2)

You should already have a version of OpenSSH installed on your Windows machine in `c:\Windows\System32\OpenSSH`. So from a command line, you can generate a key like this:

```
ssh-keygen -t rsa
```

Let it install this into your user folder (`c:\users\jacob\.ssh\id_rsa`).

Now we have to authorize that key on Unraid, by getting the public part of the key over to it.

Because you're playing with Docker on Windows with WSL2, we can use the WSL bash to get it across to Unraid. Fire up your WSL and use this command:

```
ssh-copy-id -i /mnt/c/Users/jacob/.ssh/id_rsa.pub root@tower
```

That's it! ...or is it?

## ssh-agent: agent returned different signature type
If you try to run the docker command again, you'll have to put in your password still and you'll get this error/warning `ssh-agent: agent returned different signature type`.

I found the answer and solution to this [here](https://github.com/PowerShell/Win32-OpenSSH/issues/1263#issuecomment-499542944).

It turns out the OpenSSH installation in Windows is old and incompatible. Specifically the `ssh-agent` tool isn't good enough. So you'll have to go download another [OpenSSH binary release](https://github.com/PowerShell/Win32-OpenSSH/releases) extract it to your machine and use the instructions in the link above to register the ssh-agent.exe from that location instead of the default installation.

This is crappy, but it did solve the issue on my machine. A better way to do all this is probably to run all your docker stuff directly from WSL, which would have an updated SSH.

---

Now you should be set to run your docker-compose command against the Unraid context! 

```
docker-compose --context unraid -f docker-compose.yml -f docker-compose.prod.yml up --build
```

Next up are tips for building and running the node.js applications.