【问题标题】:Why docker-compose do not use port binding as expected?为什么 docker-compose 不按预期使用端口绑定?
【发布时间】:2018-02-10 02:26:39
【问题描述】:

我正在使用这个 docker-compose 配置来运行经典的 nodejs 应用 + mysql + redis:

version: '3'

services:
  app:
    container_name: app
    restart: always
    build: 
      context: ./app/
    depends_on:
      - db
      - redis
      - elasticsearch
    links:
      - db
      - redis
      - elasticsearch
    ports:
      - "127.0.0.1:${APP_PORT}:${APP_PORT}"
    environment:
      - "PORT=${APP_PORT}"
      - "MYSQL_PORT=${MYSQL_PORT}"
      - "REDIS_PORT=${REDIS_PORT}"

  redis:
    container_name: redis
    image: "redis:3-alpine"
    restart: always
    ports:
      - "127.0.0.1:${REDIS_PORT}:6379"

  db:
    container_name: db
    image: mariadb:10.0.30
    restart: always
    volumes:
      - "${MYSQL_DATA_LOCATION}/data:/var/lib/mysql:delegated"
      - "${MYSQL_DATA_LOCATION}/my.cnf:/etc/mysql/my.cnf:ro"
    ports:
      - "127.0.0.1:${MYSQL_PORT}:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}"
      - "MYSQL_USER=${MYSQL_USER}"
      - "MYSQL_PASSWORD=${MYSQL_PASSWORD}"
      - "MYSQL_DATABASE=${MYSQL_DATABASE}"

我还在使用包含以下值的 .env 文件:

APP_PORT=5000
MYSQL_PORT=3306
REDIS_PORT=6379

然后我启动应用程序

docker-compose up -d

以这种方式一切都运行良好。我可以更改mysql端口而不会出错,但是如果我将redis端口更改为原始端口以外的其他端口,当我使用此配置时,应用程序中会出现以下错误:

redis.createClient({host: 'redis', port: process.env.REDIS_PORT });

我收到以下消息:

Error: Redis connection to redis:5555 failed - connect ECONNREFUSED 172.18.0.3:5555

而数据库和应用程序之间的连接工作正常:s

在 docker ps 中,我可以看到机器以预期的配置启动:

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                                                NAMES
9c594c6d98b8        nginx:mainline-alpine          "nginx -g 'daemon of…"   33 seconds ago      Up 39 seconds       0.0.0.0:2000->80/tcp                                 webproxy
62d1f917d7ff        app                            "npm run docker-debug"   36 seconds ago      Up 42 seconds       127.0.0.1:5000->5000/tcp, 127.0.0.1:9222->9222/tcp   app
7c982d543a7d        mariadb:10.0.30                "docker-entrypoint.s…"   39 seconds ago      Up 45 seconds       127.0.0.1:4000->3306/tcp                             db
9dd13967b37d        redis:3                        "docker-entrypoint.s…"   39 seconds ago      Up 44 seconds       127.0.0.1:5555->6379/tcp                             redis

我在这里可以看到db是从4000映射到3306的,这样可以的,但是redis从5555到6379的映射被忽略了。如果我手动将应用程序连接中的端口更改为端口 6379,它确实可以工作...

我的配置中是否缺少某些内容?

【问题讨论】:

  • 你确定图像“redis:3-alpine”使用的是 6379 吗?错误消息中提到的5555是从哪里来的?再次查看您的 docket-compose.yml 文件。
  • @zipzit 是的,我可以用 docker inspect redis 命令看到它

标签: docker redis docker-compose


【解决方案1】:

redis 在容器内在端口 6379 期间运行(如果您不更改其配置中的端口)。在您的主机上,您将端口 5555 映射到 redis 容器 6379。docker-compose 中的所有服务彼此可见,您甚至不需要将这些端口公开给主机。在您的应用程序设置中,如果您通过redis://redis:6379 访问redis 将起作用,或者使用暴露的端口redis://HOST_IP:5555 也将起作用

【讨论】:

  • 感谢您的回答。确实从应用程序我可以使用端口 6379,但为什么我不能使用端口 5555?将应用程序客户端连接到此端口时出现连接错误,我在 db 容器上没有此问题
  • 因为容器redis不知道任何端口5555。这个端口只存在于主机上。
  • 对不起,如果我不清楚,但我的问题是:为什么应用程序无法使用 redis://redis:5555 连接到 redis,而我可以使用 mysql://db:4000 连接到 db ?