【问题标题】:Running commands on docker container from the host从主机在 docker 容器上运行命令
【发布时间】:2020-07-28 14:20:47
【问题描述】:

代码优先,这样更容易解释我所追求的。

docker-compose.yml

version: '3.4'

services:
  db:
    user: '${UID}:${GID}'
    image: postgres
    container_name: postgres
    ports:
      - '5432:5432'
    restart: always
    environment:
      POSTGRES_HOST: db
      POSTGRES_USER: root
      POSTGRES_PASSWORD: secret
      POSTGRES_DATABASE: foo
      PGDATA: /var/lib/postgresql/data/db
    volumes:
      - ./db/data:/var/lib/postgresql/data/db
      - db-init.sh:/docker-entrypoint-initdb.d/:ro

  cache:
    image: redis:alpine
    container_name: redis
    sysctls:
      net.core.somaxconn: '511'
    ports:
      - '6379:6379'
    command: ['--requirepass "secret"']

  api:
    image: node:alpine
    container_name: api
    working_dir: /var/www/app
    command: sh -c "npm start"
    ports:
      - '5000:5000'
    volumes:
      - node_modules:/var/www/app/node_modules
      - .:/var/www/app
    env_file: .env
    depends_on:
      - db
      - cache

volumes:
  node_modules:

postgresnode.js 应用的连接设置:

export const {
  POSTGRES_USER = 'root',
  POSTGRES_PASSWORD = 'secret',
  POSTGRES_HOST = 'db',
  POSTGRES_PORT = 5432,
  POSTGRES_DATABASE = 'foo',
} = process.env

问题

将服务或容器名称(dbpostgres)用于 POSTGRES_HOST 设置的 node 应用程序时:

  1. 我可以成功连接并查询数据库。
  2. 无法从主机运行影响容器的命令。例如,播种 db 将不起作用:

    npx knex --esm seed:run

这是有道理的,因为db / postgres 的 DNS 解析由 docker 负责,而这些解析仅在连接容器的网络上有意义。从主机运行并针对该容器的命令将失败,因为主机不知道如何在此处解析 DNS。

另一方面,当将localhost 用于node 应用程序的POSTGRES_HOST 设置时:

  1. apipostgres 的查询将失败。
  2. 从主机运行的命令,例如npx knex --esm seed:run,将会成功。

同样,这完全有道理。由于docker-compose.yml 中的端口转发,从主机将容器寻址为localhost 将起作用。但在容器的上下文中,它指的是那个容器:因为api localhost 意味着它自己,它试图在localhost:5432api:5432 上查找数据库。

我想拥有工作的容器间网络,并从主机运行命令,寻址所述容器。我知道实现这一目标的两种方法:

  1. 使用容器/服务名称作为POSTGRES_HOST,并对容器运行命令:

    docker exec -it <container_name> <command>

  2. 将静态ips 分配给容器并使用它们而不是服务/容器名称。

我还有其他选择吗?

【问题讨论】:

    标签: node.js postgresql docker docker-compose


    【解决方案1】:

    由于您要在主机上公开数据库端口,因此您可以执行以下操作。

    • 为 POSTGRES_HOST 使用服务或容器名称(db 或 postgres),这样它将适用于 Docker 容器。
    • 当您从主机运行种子命令时,覆盖 POSTGRES_HOST。这可以通过这种方式完成
    $ export POSTGRES_HOST=127.0.0.1
    $ npx knex --esm seed:run
    
    

    或一步到位

    $ POSTGRES_HOST=127.0.0.1 npx knex --esm seed:run
    

    【讨论】:

    • 我忘了提到这种方法。它工作得很好,但是 - 在我看来 - 它既不优雅也不便携。
    • 我想说,这里的整个想法是不现实的,只是我适用于开发环境。你能解释一下为什么需要这个吗?
    • 正是如此,开发的轻松和舒适。
    • 如果问题仅与迁移有关,您可以切换到使用将执行迁移的自定义 docker 入口点,然后启动服务器。因此,您只需在引入新迁移并希望应用它时重新部署容器
    • puls,在这里使用 env 是您的最佳选择或使用 docker-compose run or docker-compose exec
    猜你喜欢
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 2015-10-21
    • 2021-06-22
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多