Minio Docker 搭建
创建数据和配置目录
mkdir -p /opt/minio/{data,config,init}
cd /opt/minio创建docker-compose.yml
注意: 此配置中 minio 的环境变量不能设置MINIO_SERVER_URL(文章末尾会有说明),除非服务器做了 FQDN,否则会出现webui页面登录不上的情况,即报错{"message":"invalid Login"},但可配置MINIO_BROWSER_REDIRECT_URL做webui的重定向。
以下的镜像是minio最后一个带web控制台的版本,如果需要最新版本请参考Minio官方文档。
version: "3.8"
services:
minio:
image: minio/minio:RELEASE.2025-04-22T22-12-26Z
container_name: minio
restart: unless-stopped
# 对外端口:9000(S3 API) 9001(Console)
ports:
- "9000:9000"
- "9001:9001"
# 数据和配置持久化
volumes:
- ./data:/data
- ./config:/root/.minio
# 生产建议:用 .env 管理账号密码
environment:
# 管理员账号密码(必须设置;不建议用默认值)
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
# 可选:设置对外显示的访问地址
# 未做 FQDN 不要设置
# MINIO_DOMAIN=example.com
# 服务器地址,未做 FQDN 不要设置
# MINIO_SERVER_URL=http://example.com
# 控制台地址,仅设置 重定向 控制台地址
# MINIO_BROWSER_REDIRECT_URL: "https://console.example.com"
# 启动命令
command: server /data --console-address ":9001"
# 健康检查:MinIO 自带 health endpoint
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 10s
timeout: 5s
retries: 5配置 .env
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=Password_123!启动
在 docker-compose.yml 所在目录运行:
docker-compose up -d题外话
(可选)自动初始化
创建 Bucket、创建普通用户、设置策略 可以把初始化脚本放在
init目录,容器启动时会自动执行。 例如,创建一个init/setup.sh:
#!/bin/bash
mc alias set local http://localhost:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
mc mb local/my-bucket
mc admin user add local myuser MyUserPassword123!
mc admin policy set local readwrite user=myuser然后在 docker-compose.yml 中添加挂载:
volumes:
- ./data:/data
- ./config:/root/.minio
- ./init:/docker-entrypoint-init.d脚本会在 MinIO 启动后自动运行一次,完成初始化工作。
(可选)Nginx 反向代理
注意:
- MinIO 控制台(默认端口 9001)和 S3 API(默认端口 9000)是两个不同的服务。
- 理论上 MinIO 控制台和 S3 API 可以共用一个域名,但在实际使用中可能会遇到 CORS 和签名验证问题,建议分别使用不同的子域名。
- 以下配置我将MinIO控制台放在了同一个域名下的
web-ui,那么docker-compose中的MINIO_BROWSER_REDIRECT_URL也需要相应修改。
以下是共用一个域名的最小 Nginx 示例配置:
location /web-ui/ {
rewrite ^/web-ui/(.*) /$1 break;
proxy_set_header Host $http_host;
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 X-NginX-Proxy true;
# This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# To support websockets in MinIO versions released after January 2023
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
# Uncomment the following line to set the Origin request to an empty string
# proxy_set_header Origin '';
chunked_transfer_encoding off;
proxy_pass http://localhost:9011; # This uses the upstream directive definition to load balance
}
# 为了防止直接访问 S3 API 根路径跳转到 web UI,单独处理根路径请求。
location = / {
# return 404;
return 200 "S3 endpoint";
add_header Content-Type text/plain;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 关键配置:禁用 HEAD 请求转换,避免 S3 V4 签名失效
proxy_cache_convert_head off;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://localhost:9010/;
}
(可选)单机多盘挂载
如果服务器有多块磁盘,可以通过绑定挂载的方式,把多块磁盘都挂载到 MinIO 容器中,例如:
volumes:
- /mnt/disk1:/data/disk1
- /mnt/disk2:/data/disk2
- /mnt/disk3:/data/disk3
- /mnt/disk4:/data/disk4docker-compose 的 command 也需要相应修改:
command: server /data/disk1 /data/disk2 /data/disk3 /data/disk4 --console-address ":9001"(可选)关于 MINIO_SERVER_URL
关于文章顶部提到的不设置 MINIO_SERVER_URL 环境变量的说明:
-
不是“不能设置 MINIO_SERVER_URL”,而是一旦设置了 MINIO_SERVER_URL,MinIO Console 会把它当作“后端 Server 的对外可访问地址”去回连/校验;如果这个地址在 容器/宿主机网络视角 下不可达(典型就是:域名没解析、解析到外网、回环被阻断、TLS 不信任、走 CDN/WAF 导致回源不通),Console 登录就会失败,并且经常“误报”为 {“message”:“invalid login”}。
-
MinIO Console 的登录流程并不只是“前端校验账号密码”,它还要跟 MinIO Server 通信完成认证/令牌流程;当 Console 连不上它认为的 Server 地址时,前端有些版本会统一返回 Invalid Login。参考
什么情况下需要设置 MINIO_SERVER_URL?
它主要服务于这些场景:
- 多节点分布式 MinIO
- 每个节点有明确、稳定、对等可达的公网/内网 FQDN
- 没有反代、或反代对节点是“透明的”
例如:
node1.minio.local
node2.minio.local
node3.minio.local
node4.minio.local这种环境里:
- 节点互访靠 FQDN
- Console 不会走“绕一圈再回自己”的路径
它是给 MinIO 自己内部 用的(尤其是 Console)
在 Docker + 反代 + 单机场景下,不推荐显式设置 MINIO_SERVER_URL,因为它很容易破坏 Console 的自举假设。
MINIO_SERVER_URL 不是“给客户端用的”,而是“给 MinIO Console 用的”,它告诉 Console 去哪里找后端 Server。
实际上:
- S3 客户端 完全不读这个变量
- SDK / 浏览器 / 下载链接 完全不依赖它
- 反代/Nginx 也不需要它
Console 会信任你写的这个地址
并在登录、token、redirect、一些 API 拼接中使用它
单机+Nginx设置了MINIO_SERVER_URL会怎么样?
Docker + 反代时,“对外地址 ≠ 容器可达地址” 这种情况下设置 MINIO_SERVER_URL 往往会导致 Console 连不上 Server,从而报错 Invalid Login。 现在的拓扑是:
Browser
↓ https://example.com (443)
Nginx (host)
↓ http://127.0.0.1:9010
MinIO Server (docker)当设置:
MINIO_SERVER_URL=https://example.comConsole(在容器里)就会:
Console (docker)
↓ https://example.com
Nginx (host)
↓ 回到 MinIO这里面任何一个点出问题(DNS、hairpin NAT、TLS、SNI、重写、location = /、子路径),Console 就会 “连不上自己”。
而 Console 的前端在这种情况下:
不会告诉你“我连不上 Server”
而是统一报:invalid login我就想设置 MINIO_SERVER_URL,怎么办?
截至目前,我尝试了docker-compose里设置extra_hosts、单独给console设置域名,都没成功。如果有大佬知道更好的方法,欢迎交流。
(废弃)在 docker-compose 里给 MinIO 容器加 hosts 映射
注意注意,
services:
minio:
extra_hosts:
- "example.com:10.0.0.4" # 改成你的宿主机内网IP或者使用 host-gateway(Docker 20.10+ 支持):
services:
minio:
extra_hosts:
- "host.docker.internal:host-gateway"
- "example.com:host-gateway"