docker-compose 和手动命令之间的区别

Difference between docker-compose and manual commands

我想做什么

我想 运行 一个 docker 容器中的 yesod web 应用程序,链接到另一个 docker 容器中的 postgres 数据库。

我试过的

我有以下文件层次结构:

/
    api/
        Dockerfile
    database/
        Dockerfile
    docker-compose.yml

docker-compose.yml 看起来像这样:

database:
    build: database
api:
    build: api
    command: .cabal/bin/yesod devel # dev setting
    environment:
        - HOST=0.0.0.0
        - PGHOST=database
        - PGPORT=5432
        - PGUSER=postgres
        - PGPASS
        - PGDATABASE=postgres
    links:
        - database
    volumes:
        - api:/home/haskell/
    ports:
        - "3000:3000"

运行 sudo docker-compose up 根本无法启动 api 容器,或者经常出现以下错误:

api_1      | Yesod devel server. Press ENTER to quit
api_1      | yesod: <stdin>: hGetLine: end of file
personal_api_1 exited with code 1

但是,如果我 运行 sudo docker-compose database up & 然后启动 api 容器而不使用 compose,而是使用

sudo docker run -p 3000:3000 -itv /home/me/projects/personal/api/:/home/haskell --link personal_database_1:database personal_api /bin/bash

我可以 exportdocker-compose.yml 文件中设置环境变量,然后手动 运行 yesod devel 并在本地主机上成功访问我的站点。

最后,如果我单独 运行 sudo docker-compose run api,我会获得第三种不同的行为。这似乎启动成功,但我无法在浏览器中访问该页面。通过 运行ning sudo docker-compose run api /bin/bash 我已经能够探索这个容器并且我可以确认在 docker-compose.yml 中设置的环境变量都已正确设置。

期望的行为

我想通过 运行 在后台连接数据库然后通过 [=59= 在 api 容器的 shell 中手动设置环境来获得我获得的结果]宁sudo docker-compose up.

问题

很明显,我尝试的三种不同方法的作用略有不同。但是根据我对 docker 和 docker-compose 的理解,我希望它们本质上是等价的。请有人解释一下它们的不同之处和原因,如果可能的话,我如何才能达到我想要的结果?

错误消息表明 API 容器需要来自命令行的输入,这需要 TTY 出现在您的容器中。

在你的 "manual" 开始,你告诉 docker 通过 -t 标志在容器中创建一个 TTY(-itv 是 shorthand -i -t -v), 所以 API 容器运行成功.

要在 docker-compose 中实现相同的效果,您必须向 docker-compose.yml 中的 API 服务添加一个 tty 键并将其设置为true;

database:
    build: database
api:
    build: api
    tty: true # <--- enable TTY for this service
    command: .cabal/bin/yesod devel # dev setting