# Setting Up a Custom Docker Container with SSL in FlyWP

Source: https://flywp.com/docs/server/setting-up-a-custom-docker-container-with-ssl-in-flywp/

This guide shows you how to run any custom Docker container on your FlyWP server and secure it with a free, auto-renewing Let’s Encrypt SSL certificate. The setup uses the server’s existing `nginx-proxy` to automatically handle traffic routing and SSL termination.

**Prerequisites:**

- A server managed by FlyWP.
- A user account with permissions to run Docker commands or sudo permission (default fly user).
- A domain (e.g., `app.yourdomain.com`) with its **DNS A record** pointing to your server’s public IP address.

### How It Works 💡

This setup relies on two key containers working together:

1. <strong>`nginx-proxy`</strong>: This container (already running on your server) acts as a reverse proxy. It detects new containers on its network and uses their environment variables to automatically create the necessary NGINX configuration to route traffic to them. The key variables are:
   - <strong>`VIRTUAL_HOST`</strong>: The domain name for your application.
   - <strong>`VIRTUAL_PORT`</strong>: The internal port your application listens on inside its container.
2. <strong>`letsencrypt-nginx-proxy-companion`</strong>: This is a helper container you’ll add. It works with `nginx-proxy` to handle SSL. It watches for containers with specific variables and automatically obtains and renews SSL certificates for them. The key variables are:
   - <strong>`LETSENCRYPT_HOST`</strong>: The domain to secure with SSL (should match `VIRTUAL_HOST`).
   - <strong>`LETSENCRYPT_EMAIL`</strong>: Your email, used for certificate registration and renewal notices.

### Step 1: Create a Shared Docker Network (Recommended)

While optional, creating a dedicated network for your proxy and applications is a best practice. It keeps your containers organised and ensures they can communicate. If you haven’t created one already, run this command:

```
docker network create proxy-network
```

After creating the network, ensure the main `nginx-proxy` container is connected to it.

```
docker network connect proxy-network nginx-proxy
```

:::note
This command might return an error if the container is already on the network; this is safe to ignore. You can also use FlyWP’s existing proxy network. Replace every mention of `nginx-proxy` network with `site-network`.
:::

### Step 2: Deploy the Let’s Encrypt Companion (One-Time Setup)

Next, deploy the Let’s Encrypt companion container. You only need to do this **once per server**. This container will manage certificates for all your future applications.

```
docker run -d \  --name nginx-letsencrypt \  --restart unless-stopped \  --volumes-from nginx-proxy \  -v /var/run/docker.sock:/var/run/docker.sock:ro \  -v /etc/acme.sh:/etc/acme.sh \  --network proxy-network \  --restart unless-stopped \  jrcs/letsencrypt-nginx-proxy-companion
```

This container is now running and waiting for you to launch applications that need an SSL certificate.

### Step 3: Deploy Your Application with SSL 🚀

You can now deploy your application. The `nginx-proxy` container will auto-detect everything from the environment variables you set. As long as your DNS is set properly, SSL will be activated automatically. Here’s how to do it using both `docker run` and `docker-compose`.  
  
Here we will be using a simple hello-world Docker container.

#### Using `docker run`

This is a direct command to run a container. Stop and remove any old version of your app container first (`docker stop my-app && docker rm my-app`).

```
docker run -d \  --name my-custom-app \  --restart unless-stopped \  -e "VIRTUAL_HOST=app.yourdomain.com" \  -e "VIRTUAL_PORT=80" \  -e "LETSENCRYPT_HOST=app.yourdomain.com" \  -e "LETSENCRYPT_EMAIL=your-email@example.com" \  --network proxy-network \  nginxdemos/hello
```

#### Using `docker-compose`

For more complex applications, `docker-compose` is the recommended method.

- Create a file named `docker-compose.yml`:

```
version: "3.7"services:  my-custom-app:    image: nginxdemos/hello    container_name: my-custom-app    restart: unless-stopped    networks:      - proxy-network    environment:      - VIRTUAL_HOST=app.yourdomain.com      - VIRTUAL_PORT=80      - LETSENCRYPT_HOST=app.yourdomain.com      - LETSENCRYPT_EMAIL=your-email@example.comnetworks:  proxy-network:    external: true
```

- From the same directory, run your application: `docker compose up -d`

### Success! ✅

That’s it! As long as your DNS settings are correct, the companion container will obtain a certificate and `nginx-proxy` will begin routing traffic for <strong>`https://app.yourdomain.com`</strong> to your new container, with SSL fully enabled. The certificate will automatically renew when needed.

### Troubleshooting: In Case of Errors 🔍

If your site is not working as expected or the SSL certificate isn’t activated, the first and most important step is to **check the logs** of the Let’s Encrypt companion container.

To view the logs, run this command on your server:

```
docker logs nginx-letsencrypt
```

For a real-time view, which is helpful when launching a new container, use the `--follow` or `-f` flag:

```
docker logs -f nginx-letsencrypt
```

Look for messages related to your domain name. The logs are very descriptive and will almost always tell you the exact cause of the problem, such as:

- **DNS problems**: The log will state that it couldn’t verify your domain because its A record does not point to your server’s IP address.
- **Rate limits**: Let’s Encrypt has limits on how often you can request a certificate. The log will mention if you’ve been temporarily blocked.
- **Connection issues**: A timeout error could indicate a firewall is blocking port 80, which Let’s Encrypt requires for validation.
