我希望标题足够描述。我试图在docker中执行我的节点应用程序(使用mongo和mysql)。我正在使用docker-compose
启动应用,并在下面显示docker-compose.yml
文件:
version: "3.3"
services:
app:
container_name: app
restart: always
build: .
volumes:
- ./:/app
ports:
- "3000:3000"
links:
- mongo
- mysql
mongo:
container_name: mongo
image: mongo
ports:
- "27017:27017"
mysql:
container_name: mysql
image: mysql
ports:
- "3306:3306"
每当我尝试使用docker-compose up
启动时,我都会收到以下错误:
ERROR: for mysql Cannot start service mysql: driver failed programming external connectivity on endpoint mysql (785b03daaa662bb3c344025f89fd28f49eabb43104b1c9a16ab425ab5120309f): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: for mysql Cannot start service mysql: driver failed programming external connectivity on endpoint mysql (785b03daaa662bb3c344025f89fd28f49eabb43104b1c9a16ab425ab5120309f): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.
我做了一些研究,似乎gitlab-runner
正在使用mysql服务。我的理解是,如果我通过docker容器运行此设置,它们将与主机系统隔离,因此我不会遇到任何端口冲突。我公开的唯一端口是我Dockerfile
中的端口 - 在我的情况下是3000.我错过了docker-compose.yml
中的内容吗?还有什么可能是错的?
答案 0 :(得分:3)
停止绑定到本地端口,让docker-compose
为您选择一个短暂的端口。在您的情况下,您的应用程序可以在没有任何帮助的情况下进入默认端口如果您遵循12 Factor App方法,请使用以下代码段中的环境变量。
version: "3.3"
services:
app:
restart: always
build: .
volumes:
- ./:/app
ports:
- 3000 # will be bound to an ephemeral port
environment:
MONGODB_URL: mongodb://mongo/db # can reach port 27017 without help
mongo:
image: mongo
ports:
- 27017
这是通过环境变量或命令行标志配置应用程序的主要原因。
如果您需要从主机访问docker应用程序,可以使用docker-compose port获取临时端口。我经常使用如下的shell函数:
get_exposed_port() { # SERVICE PORT
docker-compose port $1 $2 | cut -d: -f2
}
答案 1 :(得分:2)
从docker compose版本3开始可用的另一个选项是指定通过environment variables在主机上公开的其他端口。
所以一种实现方法可能是这样的:
version: "3.3"
services:
mysql:
container_name: mysql
image: mysql
ports:
- "${MYSQL_PORT_NUMBER-:3306}:3306"
然后,如果定义了环境变量,则将使用该值。否则,将使用默认的3306
。
版本3泊坞窗的第二个功能是组成文件,如果存在一个文件,它们将read environment variables from a .env
file。 .env
文件必须位于运行docker-compose
的目录中。
最后,要调试所有这些,可以使用docker-compose config
发出变量扩展的docker compose文件。使用.env
来执行以下操作:
MYSQL_PORT_NUMBER=3307
给出以下结果:
$ docker-compose -f mysql-port-conflict.yaml config
services:
mysql:
container_name: mysql
image: mysql
ports:
- published: 3307
target: 3306
version: '3.3'
表明mysql将在主机的端口3307
上可用。当然,任何要连接到mysql的应用程序也都需要了解${MYSQL_PORT_NUMBER}
。
HTH
答案 2 :(得分:1)
在您的docker-compose.yml文件中,您通过在ports
数组中声明它们来展示主机网络空间中的端口,例如:
ports:
- "3306:3306"
如果省略这部分配置,您的容器仍然可以私下相互联系,但端口不会绑定在主机上,避免了您遇到的端口冲突。
如果您需要将端口暴露给主机以获取部分或全部服务,则必须通过更改主机端的绑定端口来自行处理冲突。例如,为了避免端口3306上的端口冲突,您可以执行以下操作:
ports:
- "3307:3306"