【问题标题】:docker-compose: how to use minio in- and outside of the docker networkdocker-compose:如何在 docker 网络内外使用 minio
【发布时间】:2019-10-30 19:39:42
【问题描述】:

我有以下 docker-compose.yml 来为我的 Laravel 应用程序运行本地环境。

version: '3'
services:
  app:
    build:
      context: .
      dockerfile: .docker/php/Dockerfile
    ports:
      - 80:80
      - 443:443
    volumes:
      - .:/var/www:delegated
    environment:
      AWS_ACCESS_KEY_ID: minio_access_key
      AWS_SECRET_ACCESS_KEY: minio_secret_key
      AWS_BUCKET: Bucket
      AWS_ENDPOINT: http://s3:9000
    links:
      - database
      - s3
  database:
    image: mariadb:10.3
    ports:
      - 63306:3306
    environment:
      MYSQL_ROOT_PASSWORD: secret
  s3:
    image: minio/minio
    ports:
      - "9000:9000"
    volumes:
      - ./storage/minio:/data
    environment:
      MINIO_ACCESS_KEY: minio_access_key
      MINIO_SECRET_KEY: minio_secret_key
    command: server /data

如您所见,我使用 minio 作为与 AWS S3 兼容的存储。这很好用,但是当我为文件 (Storage::disk('s3')->url('some-file.txt')) 生成一个 url 时,显然我得到了一个像 http://s3:9000/Bucket/some-file.txt 这样的 url,它在 Docker 网络之外不起作用。

我已经尝试将 AWS_ENDPOINT 设置为 http://127.0.0.1:9000 但 Laravel 无法连接到 Minio 服务器...

有没有办法配置 Docker / Laravel / Minio 以生成可在 Docker 网络内外访问的 url?

【问题讨论】:

标签: laravel docker amazon-s3 minio


【解决方案1】:

将“s3”别名添加到我的本地主机文件并没有解决问题。但是明确地将端口绑定到 127.0.0.1 就像一个魅力:

s3:
    image: minio/minio:RELEASE.2022-02-05T04-40-59Z
    restart: "unless-stopped"
    volumes:
        - s3data:/data
    environment:
        MINIO_ROOT_USER: minio
        MINIO_ROOT_PASSWORD: minio123
    # Allow all incoming hosts to access the server by using 0.0.0.0
    command: server --address 0.0.0.0:9000 --console-address ":9001" /data
    ports:
        # Bind explicitly to 127.0.0.1
        - "127.0.0.1:9000:9000"
        - "9001:9001"
    healthcheck:
        test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live"]
        interval: 30s
        timeout: 20s
        retries: 3

【讨论】:

    【解决方案2】:

    我没有找到使用 docker-compose 的完整 minio 设置。在这里:

    version: '2.4'
    
    services:
      s3:
        image: minio/minio:latest
        ports:
          - "9000:9000"
          - "9099:9099"
        environment:
          MINIO_ROOT_USER: minioadmin
          MINIO_ROOT_PASSWORD: minioadmin
        volumes:
          - storage-minio:/data
        command: server --address ":9099" --console-address ":9000" /data
        restart: always # necessary since it's failing to start sometimes
    
    volumes:
      storage-minio:
        external: true
    

    在命令部分我们有 address 这是 API 地址 我们有 console-address 您可以连接到控制台查看下图。使用 MINIO_ROOT_USERMINIO_ROOT_PASSWORD 值登录。

    【讨论】:

    • 据我所知,这并不能解决问题。该服务仍然可以通过两个不同的主机名访问,具体取决于您尝试连接的位置。
    • 我的回答提供了使用 docker-compose 的完整 minio 设置以及如何使用 minio 控制台。
    • 控制台和 API 都从容器中公开。如果你不想这样,你可以在设置中注释上面的端口。
    • 你是对的,我认为这可能对希望使用 Docker 设置 MinIO 的人有所帮助。但这并不能解决@Nio遇到的问题:如何合并用于联系服务的两个主机?您可以使用s3(Docker 内部)或localhost(Docker 外部),但没有适用于这两种环境的主机。
    • 那么,OP 如何使用您的解决方案生成一个在容器内部和外部都有效的 S3 URL? --address 参数只是将服务器绑定到地址/端口组合。它不会改变生成的 URL 在 Docker 内部和外部都不起作用的事实。如果我错了,请纠正我,我很高兴学习。
    【解决方案3】:

    对于那些正在寻找 s3 与 minio 对象服务器集成测试的人。专门用于 JAVA 实现。

    docker-compose 文件:

    version: '3.7'
    services:
      minio-service:
        image: quay.io/minio/minio
        command: minio server /data
        ports:
          - "9000:9000"
        environment:
          MINIO_ROOT_USER: minio
          MINIO_ROOT_PASSWORD: minio123
    

    实际的 IntegrationTest 类:

    import com.amazonaws.auth.AWSStaticCredentialsProvider;
    import com.amazonaws.auth.BasicAWSCredentials;
    import com.amazonaws.client.builder.AwsClientBuilder;
    import com.amazonaws.regions.Regions;
    import com.amazonaws.services.s3.AmazonS3;
    import com.amazonaws.services.s3.AmazonS3ClientBuilder;
    import com.amazonaws.services.s3.model.S3Object;
    import org.junit.jupiter.api.*;
    import org.testcontainers.containers.DockerComposeContainer;
    
    import java.io.File;
    
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    class MinioIntegrationTest {
    
        private static final DockerComposeContainer minioContainer = new DockerComposeContainer<>(new File("src/test/resources/docker-compose.yml"))
                .withExposedService("minio-service", 9000);
        private static final String MINIO_ENDPOINT = "http://localhost:9000";
        private static final String ACCESS_KEY = "minio";
        private static final String SECRET_KEY = "minio123";
        private AmazonS3 s3Client;
    
        @BeforeAll
        void setupMinio() {
            minioContainer.start();
            initializeS3Client();
        }
    
        @AfterAll
        void closeMinio() {
            minioContainer.close();
        }
    
        private void initializeS3Client() {
            String name = Regions.US_EAST_1.getName();
            AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(MINIO_ENDPOINT, name);
             s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
                    .withEndpointConfiguration(endpoint)
                    .withPathStyleAccessEnabled(true)
                    .build();
        }
    
        @Test
        void shouldReturnActualContentBasedOnBucketName() throws Exception{
            String bucketName = "test-bucket";
            String key = "s3-test";
            String content = "Minio Integration test";
            s3Client.createBucket(bucketName);
            s3Client.putObject(bucketName, key, content);
            S3Object object = s3Client.getObject(bucketName, key);
            byte[] actualContent = new byte[22];
            object.getObjectContent().read(actualContent);
            Assertions.assertEquals(content, new String(actualContent));
        }
    }
    

    【讨论】:

      【解决方案4】:

      绑定地址呢? (未测试)

      ...
        s3:
          image: minio/minio
          ports:
            - "9000:9000"
          volumes:
            - ./storage/minio:/data
          environment:
            MINIO_ACCESS_KEY: minio_access_key
            MINIO_SECRET_KEY: minio_secret_key
          command: server --address 0.0.0.0:9000 /data
      

      【讨论】:

      • 我认为这不会解决问题,因为这不会提供可以从 Docker 服务从主机使用的单个主机名。
      • 命令部分已更改:command: server /data --console-address ":9001"
      【解决方案5】:

      我扩展了这个问题中的解决方案,以创建一个在本地主机和具有可访问 dns 的服务器上都适用于我的解决方案。

      本地主机解决方案本质上就是上面描述的解决方案。

      创建 localhost 主机映射

      sudo echo "127.0.0.1       my-minio-localhost-alias" >> /etc/hosts
      

      设置 HOSTNAME,使用 'my-minio-localhost-alias' 作为 localhost

      export HOSTNAME=my-minio-localhost-alias
      

      创建 hello.txt

      Hello from Minio!
      

      创建 docker-compose.yml

      此撰写文件包含以下容器:

      • minio:minio 服务
      • minio-mc:用于初始化内容的命令行工具
      • s3-client:命令行工具生成预签名的url
      version: '3.7'
      networks:
        mynet:
      services:
        minio:
          container_name: minio
          image: minio/minio
          ports:
          - published: 9000
            target: 9000
          command: server /data
          networks:
            mynet:
              aliases:
              # For localhost access, add the following to your /etc/hosts
              # 127.0.0.1       my-minio-localhost-alias
              # When accessing the minio container on a server with an accessible dns, use the following
              - ${HOSTNAME}
        # When initializing the minio container for the first time, you will need to create an initial bucket named my-bucket.
        minio-mc:
          container_name: minio-mc
          image: minio/mc
          depends_on:
          - minio
          volumes:
          - "./hello.txt:/tmp/hello.txt"
          networks:
            mynet:
        s3-client:
          container_name: s3-client
          image: amazon/aws-cli
          environment:
            AWS_ACCESS_KEY_ID: minioadmin
            AWS_SECRET_ACCESS_KEY: minioadmin
          depends_on:
          - minio
          networks:
            mynet:
      
      

      启动minio容器

      docker-compose up -d minio
      

      在minio中创建bucket并加载文件

      docker-compose run minio-mc mc config host add docker http://minio:9000 minioadmin minioadmin
      docker-compose run minio-mc mb docker/my-bucket
      docker-compose run minio-mc mc cp /tmp/hello.txt docker/my-bucket/foo.txt
      

      创建一个可在 docker 网络内外访问的预签名 URL

      docker-compose run s3-client --endpoint-url http://${HOSTNAME}:9000 s3 presign s3://my-bucket/hello.txt
      

      【讨论】:

        【解决方案6】:

        由于您将主机上的 9000 端口映射到该服务,如果您只需将 s3 添加到主机文件(Mac/Linux 上的 /etc/hosts),您应该能够通过 s3:9000 访问它

        将此127.0.0.1 s3 添加到您的主机文件中,您应该能够使用https://s3:9000/path/to/file 从您的主机访问s3 容器

        这意味着您可以在 docker 网络内外使用 s3 主机名

        【讨论】:

        • 我已经考虑过了,但这对我来说更像是一种解决方法。
        • 这实际上并不是一种解决方法,因为在本地开发环境中,有时事情就是这样工作的……您在开发它们时没有将 Web 应用程序主机名添加到主机文件中吗?您还可以设置在您的主机上运行的代理服务器,并将 s3 的请求转发到 localhost。或者干脆让主机上的 minio 服务完全不可用,并使用 docker-compose 项目中的 nginx 代理服务处理 9000 端口请求
        • 有同样的问题,我同意@Nio 这不是一个理想的解决方案,即使它是唯一的解决方案。不应该对本地 DNS 配置有任何需求,假设应用程序可以从 localhost 运行,并且如果 minio 只是整个应用程序的一小部分,那么 nginx 代理层似乎有点矫枉过正。似乎最好的解决方案是 Minio 在生成其签名 URL 时允许使用替代主机名,但看起来没有任何动作:github.com/minio/minio/issues/2848
        • 嗯,这是一个我们可以自己做的解决方案......坐下来希望开发人员在他们的工具上实现功能不会太有效率。您可能可以尝试创建一个代理服务器,通过该代理服务器使用 nginx 或其他轻量级解决方案提供所有文件
        • 两点都同意,你的答案可能是目前唯一的选择。似乎很奇怪,这在任何地方都没有得到广泛解决,即使是与 Minio 类似的工具(FakeS3 等)似乎也没有考虑这个用例。现在很多人在运行 docker-compose,如果他们试图在本地复制他们的基础设施,他们可能会遇到这种情况。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-09
        • 2019-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-27
        相关资源
        最近更新 更多