docker-compose和手动命令的区别

我正在尝试做什么

我想在一个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文件中设置的环境variables,然后手动运行yesod devel并在本地主机上成功访问我的站点。

最后,如果我运行sudo docker-compose run api ,我会得到第三种不同的行为。 这似乎开始成功,但我不能访问我的浏览器页面。 通过运行sudo docker-compose run api /bin/bash我已经能够探索这个容器,我可以确认在docker-compose.yml中设置的环境variables都设置正确。

期望的行为

我想从后台运行数据库中获得结果,然后通过简单地通过运行sudo docker-compose up手动设置api容器的shell中的环境。

显然,我尝试的三种不同的方法做了些微不同的事情。 但是从我对docker和docker的理解来看,我期望它们在本质上是等价的。 请有人可以解释他们如何以及为什么会有所不同,如果可能的话,我可以如何实现我想要的结果?

该错误消息表明API容器正在等待来自命令行的input,该命令行期望在您的容器中存在TTY。

在你的“手动”开始,你告诉-itv通过-t标志在容器中创build一个TTY( -itv-i -t -v缩写),所以API容器成功运行。

要在docker-compose中实现相同的function,您必须在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