从主机在Docker容器上运行命令

时间:2020-04-15 14:48:18

标签: node.js postgresql docker docker-compose

首先输入代码,解释之后的内容会更容易。

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:
node.js应用的

postgres 连接设置:

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

问题

db应用的postgres设置中使用服务或容器名称(POSTGRES_HOSTnode)时:

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

    npx knex --esm seed:run

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

另一方面,在localhost应用的POSTGRES_HOST设置中使用node时:

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

同样,这很合理。由于localhost中的端口转发,因此可以从主机将容器命名为docker-compose.yml。但是在容器的上下文中,它指的是那个容器:因为api localhost表示自身,并且试图在localhost:5432api:5432上查找数据库。 / p>

我希望容器间网络正常工作,并且还希望从主机运行命令,以解决上述容器问题。我知道有两种方法可以实现这一目标:

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

    docker exec -it <container_name> <command>

  2. 为容器分配静态ip,并使用它们代替服务/容器名称。

我在这里还有其他选择吗?

1 个答案:

答案 0 :(得分:0)

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

  • 将服务或容器名称(db或postgres)用于POSTGRES_HOST,这样,它将适用于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