How to run multiple MinIO servers with Træfɪk Slack

Træfɪk is a modern reverse proxy also written in Go. It
supports multiple ways to get configured, this cookbook will explain how you
can setup multiple MinIO instances via Docker which you can access on different
sub-domains through Træfɪk.

1. Prerequisites

You have Docker installed and running, if not follow install instructions.

2. Steps

Fetch, configure and launch Træfɪk

First of all you should create a configuration file for Træfɪk to enable Let's
Encrypt and to configure the Docker backend. Incoming traffic via HTTP gets
automatically redirected to HTTPS and the certificates are getting created on
demand by the integrated Let's Encrypt support.

cat << EOF > traefik.toml
defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
    address = ":80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]

[acme]
email = "your@email.com"
storageFile = "/etc/traefik/acme.json"
entryPoint = "https"
onDemand = true

[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "example.com"
watch = true
EOF

Beside the configuration we should also touch the acme.json file, this file
is the storage for the generated certificates. This file will also store the
private keys, so you should set proper permissions to make sure not everybody
can read the configuration.

touch acme.json
chmod 640 acme.json

With those steps we are prepared to launch a Træfɪk container which proxies the
incoming traffic.

docker run -d \
  --restart always \
  --name traefik \
  --publish 80:80 \
  --publish 443:443 \
  --volume $(pwd)/traefik.toml:/etc/traefik/traefik.toml \
  --volume $(pwd)/acme.json:/etc/traefik/acme.json \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  traefik

Fetch, configure and launch MinIO

Now it's time to prepare multiple instances of MinIO to demonstrate a
multi-tenant solution. That way you are able to launch multiple MinIO instances
with different credentials that get routed automatically by Træfɪk.

We will launch the MinIO instances with volume mounts from the host system. If
you prefer data containers please take a look at the MinIO Docker quickstart guide.

for i in $(seq 1 5); do
    mkdir -p $(pwd)/minio${i}/{export,config}

    docker run -d \
      --restart always \
      --name minio-${i} \
      --volume $(pwd)/minio${i}/config:/root/.minio \
      --volume $(pwd)/minio${i}/export:/export \
      minio/minio
done

Test launched instances

To test the launched instances you can take curl, that way you can verify that
the instances are really launched correctly.

curl -H Host:minio-1.example.com http://127.0.0.1

This call will result in the following output because the request had been
unauthenticated, but you can see that it finally have been correctly launched.

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied.</Message><Key></Key><BucketName></BucketName><Resource>/</Resource><RequestId>3L137</RequestId><HostId>3L137</HostId></Error>

Now you can reach all the launched MinIO instances via https://minio-{1,2,3,4,5}.example.com

As a final note I would like to mention that you should start the Docker
containers with the init system of your operating system. As an example you can
see an example for a systemd service file how I'm launching new MinIO
instances. Just store this file as /etc/systemd/system/minio@.service and
start new instances with systemctl start minio@server1,
systemctl start minio@server2, systemctl start minio@server3 and the
instances will be available at server1.example.com and so on.

[Unit]
Description=MinIO: %i

Requires=docker.service
After=docker.service

[Service]
Restart=always

ExecStop=/bin/sh -c '/usr/bin/docker ps | /usr/bin/grep %p-%i 1> /dev/null && /usr/bin/docker stop %p-%i || true'
ExecStartPre=/bin/sh -c '/usr/bin/docker ps | /usr/bin/grep %p-%i 1> /dev/null && /usr/bin/docker kill %p-%i || true'
ExecStartPre=/bin/sh -c '/usr/bin/docker ps -a | /usr/bin/grep %p-%i 1> /dev/null && /usr/bin/docker rm %p-%i || true'
ExecStartPre=/usr/bin/docker pull minio/minio:latest

ExecStart=/usr/bin/docker run --rm \
  --name %p-%i \
  --volume /storage/%p/%i/files:/export \
  --volume /storage/%p/%i/config:/root/.minio \
  --label traefik.frontend.rule=Host:%i.example.com \
  --label traefik.frontend.passHostHeader=true \
  minio/minio:latest

[Install]
WantedBy=multi-user.target