Lately, I was playing around with MinIO, an open-source Object Storage, that can also be self-hosted. Basically, it’s S3 in open source.
Getting started is fairly easy: Just run it in a Docker container:
docker run --rm -v $PWD:/data -p 9000:9000 -p 9001:9001 -it minio/minio server --address ":9000" --console-address ":9001" /data
This line will create a new MinIO container, save all data in ./data
(on the host machine), makes the Object Storage available on port 9000
, the web-based console on http://localhost:9001
, and uses /data
as storage for all data within the container.
--rm
will delete the container again when it’s exited (with control + C).
But no worries, you can continue where you left off with the exact same command because everything is stored in ./data
.
The console is also quite self-explanatory. Just open http://localhost:9001
and login with minioadmin
as username and password.
One Port
So far so good.
I want to host such a MinIO Object Storage on a server.
I don’t want to expose multiple ports (here 9000
and 9001
), but ideally only port 80
.
A master-reverse-proxy is already in place that takes care of proxying the right hosts to the right containers.
However, it has one limitation: only one host per container is allowed.
Naively trying to just use the same port for --address
and --console-address
leads to this concise error:
ERROR Unable to start the server: --console-address cannot be same as --address
A little variation --address ":80" --console-address ":80/console"
, also doesn’t help:
ERROR Unable to split host port :80/console: invalid port number
That’s a pity, but understandable.
More Reverse-Proxies
My solution is to let the master-reverse-proxy connect to port 9000
of the MinIO container, and create a second reverse-proxy that is connected to port 9001
of the MinIO container (the console).
Then the master-reverse-proxy can either forward to the MinIO container for the Object Storage itself, or to the console reverse-proxy for the console.
The docker-compose.yml
configuration looks like this:
version: "3.9"
services:
minio.example.com:
image: minio/minio
command: server --address ":9000" --console-address ":9001" /data
container_name: minio_example_com_app
restart: always
expose:
- 9000
- 9001
environment:
- "MINIO_ROOT_USER=admin"
- "MINIO_ROOT_PASSWORD=my#v3erySECURE_password"
- "VIRTUAL_HOST=minio.example.com"
- "VIRTUAL_PORT=9000"
volumes:
- minio-data:/data
minio-console.example.com:
image: nginx
restart: always
expose:
- 80
ports:
- "8082:80" # TODO remove. Allows to access this container via localhost:8082 for testing.
environment:
- "VIRTUAL_HOST=minio-console.example.com"
- "VIRTUAL_PORT=80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro"
volumes:
minio-data:
The nginx.conf
, which lives in the same folder as the docker-compose.yml
:
server {
listen 80;
server_name minio-console.example.com;
location / {
proxy_pass http://minio_example_com_app:9001;
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_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_http_version 1.1;
chunked_transfer_encoding off;
}
}
When you run docker compose up --remove-orphans
in the folder that contains nginx.conf
and docker-compose.yml
, you should be able to access the console via http://localhost:8082/
.
I first had trouble accessing the “Object Browser” in the console, when it’s behind the reverse-proxy. It only showed an eternal loading indicator and the content of a bucket was never visible. The problem was that the “Object Browser” uses websockets, and the nginx configuration I had before didn’t support that. However, the configuration presented above works for me now.
The master-reverse-proxy is out of scope of this post. But a reverse-proxy like nginxproxy/nginx-proxy) picks up the VIRTUAL_HOST
environment varaible, and associates the specified host with the container. With this configuration and the right DNS entries, you should be able to access the MinIO Object Storage using minio.example.com
and the console using minio-console.example.com
.
I hope this was helpful! It certainly would have for me, before I figured this configuration out. Have fun!