目录

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 反向代理

注意:

  1. MinIO 控制台(默认端口 9001)和 S3 API(默认端口 9000)是两个不同的服务。
  2. 理论上 MinIO 控制台和 S3 API 可以共用一个域名,但在实际使用中可能会遇到 CORS 和签名验证问题,建议分别使用不同的子域名。
  3. 以下配置我将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/disk4

docker-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.com

Console(在容器里)就会:

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"