首页 > 解决方案 > 如何为 docker-compose 容器分配主机名以进行开发

问题描述

我真的是 docker 的新手,但我需要为本地开发设置它。我正在使用 docker-compose 来运行几个容器,并且我想为本地开发分配一个主机名。这是 docker-compose 文件:

version: "3.4"

services:
  php:
    build:
      context: ./api
      target: api_platform_php
    depends_on:
      - db-mysql
      - db-mongodb
    restart: unless-stopped
    volumes:
      - php_socket:/var/run/php
    healthcheck:
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s
    environment:
#      DATABASE_URL: postgresql://${POSTGRES_USER:-api-platform}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-api}?serverVersion=${POSTGRES_VERSION:-13}
      DATABASE_URL: mysql://username:password@db-mysql:3306/dbname?server_version=8
      TRUSTED_PROXIES: ${TRUSTED_PROXIES:-127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16}
      TRUSTED_HOSTS: ^${SERVER_NAME:-example\.com|localhost}|caddy$$
      MERCURE_URL: ${CADDY_MERCURE_URL:-http://caddy/.well-known/mercure}
      MERCURE_PUBLIC_URL: https://${SERVER_NAME:-localhost}/.well-known/mercure
      MERCURE_JWT_SECRET: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}

  pwa:
    build:
      context: ./pwa
      target: api_platform_pwa_prod
    environment:
      API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT: http://caddy
      NEXT_PUBLIC_ENTRYPOINT: http://caddy

  caddy:
    build:
      context: api/
      target: api_platform_caddy
    depends_on:
      - php
      - pwa
    environment:
      PWA_UPSTREAM: pwa:3000
      SERVER_NAME: ${SERVER_NAME:-localhost, caddy:80}
      MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}
      MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}
    restart: unless-stopped
    volumes:
      - php_socket:/var/run/php
      - caddy_data:/data
      - caddy_config:/config
    ports:
      # HTTP
      - target: 80
        published: 80
        protocol: tcp
      # HTTPS
      - target: 443
        published: 443
        protocol: tcp
      # HTTP/3
      - target: 443
        published: 443
        protocol: udp
        
  db-mongodb:
    # In production, you may want to use a managed database service
    image: mongo
    environment:
      - MONGO_INITDB_DATABASE=test_mongo
      - MONGO_INITDB_ROOT_USERNAME=test_mongo
      # You should definitely change the password in production
      - MONGO_INITDB_ROOT_PASSWORD=password
    volumes:
      - mongodb_db_data:/var/lib/mongodb/data:rw
      # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
      # - ./docker/db/data:/var/lib/mongodb/data:rw
    ports:
      - "27017:27017"      

  db-mysql:
    image: mysql:8
    command: mysqld --default-authentication-plugin=mysql_native_password
    restart: always
#    security_opt:
#      - seccomp:unconfirmed
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_USER=username
      - MYSQL_PASSWORD=password
      - MYSQL_DATABASE=dbname
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - target: 3306
        published: 3306
        protocol: tcp

volumes:
  php_socket:
  mysql_data:
  mongodb_db_data:  
  caddy_data:
  caddy_config:

这是 Caddyfile

{
    # Debug
    {$DEBUG}
    # HTTP/3 support
    servers {
        protocol {
            experimental_http3
        }
    }
}

{$SERVER_NAME}

log

# Matches requests for HTML documents, for static files and for Next.js files,
# except for known API paths and paths with extensions handled by API Platform
@pwa expression `(
        {header.Accept}.matches("\\btext/html\\b")
        && !{path}.matches("(?i)(?:^/docs|^/graphql|^/bundles/|^/_profiler|^/_wdt|\\.(?:json|html$|csv$|ya?ml$|xml$))")
    )
    || {path} == "/favicon.ico"
    || {path} == "/manifest.json"
    || {path} == "/robots.txt"
    || {path}.startsWith("/_next")
    || {path}.startsWith("/sitemap")`

route {
    root * /srv/api/public
    mercure {
        # Transport to use (default to Bolt)
        transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
        # Publisher JWT key
        publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
        # Subscriber JWT key
        subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
        # Allow anonymous subscribers (double-check that it's what you want)
        anonymous
        # Enable the subscription API (double-check that it's what you want)
        subscriptions
        # Extra directives
        {$MERCURE_EXTRA_DIRECTIVES}
    }
    vulcain
    push

    # Add links to the API docs and to the Mercure Hub if not set explicitly (e.g. the PWA)
    header ?Link `</docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation", </.well-known/mercure>; rel="mercure"`
    # Disable Google FLOC tracking if not enabled explicitly: https://plausible.io/blog/google-floc
    header ?Permissions-Policy "interest-cohort=()"

    # Comment the following line if you don't want Next.js to catch requests for HTML documents.
    # In this case, they will be handled by the PHP app.
    reverse_proxy @pwa http://{$PWA_UPSTREAM}

    php_fastcgi unix//var/run/php/php-fpm.sock
    encode zstd gzip
    file_server
}

使用此配置,我在 caddy 上运行 api 平台,https://localhosthttps://localhost:3000.

我想要的是打开后端https://api.mysite.local和打开 pwa https://www.mysite.local。另外,如何在本地设置证书以使 SSL 完全正常工作(对于 API)?

标签: dockerdocker-compose

解决方案


首先,顶级域.local是为mDNS(也称为AvahiBonjour )保留的,所以我不会使用它来避免混淆。

让我们使用api.mysite.local.devwww.mysite.local.dev

其次 - 我没有在 Composefile 的任何地方看到端口 3000,所以我假设您使用 Caddy 作为前端和后端的反向代理。

首先,您需要在 Caddyfile 中创建两个虚拟主机 - 例如:

www.mysite.local.dev {
    reverse_proxy php:80
}

api.mysite.local.dev {
    reverse_proxy pwa:3000
}

然后,您需要做的就是使用计算机的 hosts 文件将api.mysite.local.devwww.mysite.local.dev都指向127.0.0.1

至于 TLS,您需要为 * .mysite.local.dev生成通配符证书,然后将其挂载到容器中并使用 Caddyfile 将 Caddy 指向它。假设您将证书和密钥安装为/etc/tls/cert.pem/etc/tls/key.pem,您需要将上面的 CaddyFile 更新为:

www.mysite.local.dev {
    reverse_proxy php:80
    tls /etc/tls/cert.pem /etc/tls/key.pem
}

api.mysite.local.dev {
    reverse_proxy pwa:3000
    tls /etc/tls/cert.pem /etc/tls/key.pem
}

推荐阅读