> ## Documentation Index
> Fetch the complete documentation index at: https://docs.minimus.io/llms.txt
> Use this file to discover all available pages before exploring further.

# NGINX Tutorial

> Deploy a secure and minimal NGINX container image built by Minimus to optimize security

Getting started with the Minimus NGINX image is quick and simple, with optimal compatibility with the public NGINX image. As with any NGINX image, you can use it as an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server.

## Why make the switch?

The NGINX container image offered by Minimus is more secure, delivers daily package updates, and is drop-in ready. Visit the [risk reduction dashboard](https://images.minimus.io/gallery/images/nginx/risk-reduction) for the NGINX image to see the current vulnerability report. The image is shell-less and hardened and runs as non-root to keep your perimeter safer.

## Highlights

Here's what's special about the Minimus NGINX image:

* Runs as a non-root, unprivileged user, by default.
* Defaults to port 8080 for HTTP (instead of port 80). This change was needed for compatibility with Kubernetes when running rootless. \
  Kubernetes prevents a container running as a non-root user from binding to privileged ports (ports between 0–1023) unless explicitly allowed via security configurations.
* The Minimus NGINX image is hardened and does not include a shell so you can't simply add or edit files on the container. Instead, you can bind mount files from the host to override the default configuration file, mount static content, and more.

  In the example below, we show how to bind mount the `index.html` file to override the default directory.

  <Tip>
    Using a bind mount makes your changes persistent so they aren't lost when the container is relaunched on the same host.
  </Tip>

## Deploy an NGINX server

Serving static content with NGINX as an HTTP server is simple using bind mounts and port mappings.

To begin, authenticate to the Minimus registry:

```bash theme={null}
docker login reg.mini.dev -u minimus 
# Password: {Minimus token}
```

For starters, you can run the NGINX server in detached mode (`-d`):

```bash theme={null}
docker run -d   --name minimus-nginx /
 -p 80:8080 /
 -v /home/me/site/static:/usr/share/nginx/html:ro /
 -v /home/me/nginx.conf:/etc/nginx/nginx.conf:ro /
 reg.mini.dev/nginx:latest
```

Let's review the parameters in this command.

<Steps>
  <Step title="Map the ports">
    The `-p` flag maps port 80 on the host machine to port 8080 on your container. Minimus NGINX defaults to port 8080 so it can run as an unprivileged process anywhere, even Kubernetes.

    Here's the general command for mapping the host port to the container port:

    ```bash theme={null}
    docker run -d -p {host_port}:{container_port} {image}
    ```
  </Step>

  <Step title="Bind mount the directory file">
    Given that the container does not have a shell, editing the `html.dir` file directly in the container would require copying it back and forth and would be unnecessarily tedious.

    Instead of directly editing the directory file, it is simpler to copy the desired directory file to the host and map it to the default directory path in the NGINX configuration. See the detailed instructions below.
  </Step>

  <Step title="Bind mount the configuration file">
    You can skip this step unless you need to change any additional configurations. For example, if you want to change the default listening port from 8080 to something else.
  </Step>
</Steps>

### Replacing the default directory file

To replace the default directory file, we'll want to place the new file on the host so that the change is persistent. Then, we'll map it to the default directory path.

The default directory path (`/usr/share/nginx/html`) is specified by the root directive in the NGINX configuration file (`nginx.conf`):

```
    location / {
        root   /usr/share/nginx/html;
        index  index.html;
    }
```

First, create the new directory on your host. In this example, we'll create the `static` folder and nest it under `site`. The `-p` flag creates all the directories in the path, so it's useful for setting up nested directory structures in a single step.

```bash theme={null}
mkdir -p ~/site/static
```

Next, copy (or move) the `index.html` file to the new directory.

<CodeGroup>
  ```bash copy_file theme={null}
  cp index.html /path/to/destination/
  ```

  ```bash move_file theme={null}
  mv ~/index.html /path/to/destination/
  ```
</CodeGroup>

When you run the container, map the `index.html` file from the host to the default directory path in the configuration file. For our example, we'll add the following parameter when running the NGINX container:

```bash theme={null}
-v /home/me/site/static:/usr/share/nginx/html:ro
```

The read-only flag `:ro` is a standard best practice for protecting the container from accidentally or maliciously modifying host data.

## Docker Compose

While Docker Compose usually isn't used in production, it's a useful development and testing tool.

<Steps>
  <Step title="Prerequisite: Validate your Docker Compose version">
    Make sure you have the [Docker Compose plugin](https://docs.docker.com/compose/install/linux/#install-using-the-repository) installed. If you have the legacy standalone Docker Compose binary, you'll need to update it.

    Check your version:

    ```bash theme={null}
    docker compose version
    ```
  </Step>

  <Step title="Create the Compose file">
    Create a `compose.yaml` file that defines the NGINX service with the appropriate configurations. The configuration details are explained below.
  </Step>

  <Step title="Run the service">
    Run the Docker Compose command to start the container. Make sure you run it from the same directory where the `compose.yaml` file is located.

    ```bash theme={null}
    docker compose up -d
    ```

    The `-d` flag is for detached mode, so your terminal stays free.
  </Step>

  <Step title="Verify the container">
    Run `docker ps` to confirm that the container is running. You can run `docker inspect` to review the container's settings and status.
  </Step>

  <Step title="Visit your NGINX site">
    Now that the container is running, you can visit your NGINX site. You should see a greeting from Minimus.
  </Step>
</Steps>

### Docker Compose file example

We can use Docker Compose to create a YAML template for running our Nginx container with the appropriate bind mounts and port mapping. For our example, we'll create a `compose.yaml` file with the following code:

```
services:
  nginx:
    image: {pull URL for Minimus Nginx image}
    container_name: myNginxContainer
    ports:
      - "80:8080"
    volumes:
      - /home/me/site/static:/usr/share/nginx/html:ro
      - /home/me/nginx.conf:/etc/nginx/nginx.conf:ro
    restart: always
```

* services: defines the services to be managed by Docker Compose (`nginx` in our example).
* image: specifies the path to pull the image from.
* container\_name: sets the container's name (`myNginxContainer`).
* ports: maps port 80 on the host to port 8080 in the container (`80:8080`).
* volumes:
  * `/home/me/site/static:/usr/share/nginx/html`: mounts your static file directory to the container's HTML directory.
  * `/home/me/nginx.conf:/etc/nginx/nginx.conf`: mounts your custom NGINX configuration file to the container's config directory.
* restart: ensures the container restarts automatically if it stops.
