英文:
docker containers choosing different networks despite never setting any
问题
我在设置我的Go服务的Docker配置时遇到了很糟糕的问题。以下是我的设置概述:
name = "main_arm64",
embed = [":server_lib"],
goarch = "arm64",
goos = "linux",
visibility = ["//visibility:public"],
)
container_image(
name = "ww_server_image",
base = "@go_image_static_arm64//image",
entrypoint = ["/main_arm64"],
files = [":main_arm64"],
ports = [
"8080",
"3306",
],
)
我在http://localhost:8080
上运行了一个GraphQL Playground(HTTP),尽管端口被暴露,但我无法访问Playground的用户界面。
我所尝试做的只是:
- 能够访问GraphQL Playground和容器中运行在其他端口上的任何其他API。
- 能够从我的Docker化的Go应用程序向单独的MySQL容器发出请求(我无法弄清楚如何使用
rules_docker
将它们放在同一个网络上)。 docker exec -it ... /bin/bash
进入我的Docker容器(这没有起作用,因为bash没有安装,但我不知道如何通过container_image
命令安装bash)。
这是错误信息:
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
如果我获取生成的Docker镜像ID并运行docker run -p 8080:8080 IMAGE_ID
,我可以访问GraphQL Playground,但无法与MySQL容器通信。
如果我更改网络设置为:docker run --network=host -p 8080:8080 IMAGE_ID
,Docker化的Go应用程序可以成功与MySQL容器通信,但是GraphQL Playground变得无法访问。只有在保持--network=bridge
的情况下,才能访问GraphQL Playground。我不确定为什么MySQL没有使用bridge
,因为我在启动时没有指定网络。这是我获取MySQL容器的方式:
docker run -p 3306:3306 --name my-db -e MYSQL_ROOT_PASSWORD=testing -d mysql:8.0.31
英文:
I'm having a horrible time with setting up my Docker configuration for my go service. Below is an overview of my setup
go_binary(
name = "main_arm64",
embed = [":server_lib"],
goarch = "arm64",
goos = "linux",
visibility = ["//visibility:public"],
)
container_image(
name = "ww_server_image",
base = "@go_image_static_arm64//image",
entrypoint = ["/main_arm64"],
files = [":main_arm64"],
ports = [
"8080",
"3306",
],
)
I have a GraphQL Playgroud (HTTP) running on http://localhost:8080
, and despite the port supposedly being exposed, i cant access the playground UI.
All I'm trying to do is:
- Be able to access the GraphQL playground and any other APIs running on other ports within the container
- Be able to make requests from my Dockerized Go app to a separate MySQL container (I can't figure out how to put them on the same network with
rules_docker
). docker exec -it ... /bin/bash
into my docker container (this hasnt been working because bash isnt installed, yet i have no idea how to install bash via this container_image command)
Here is the error:
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
If i take the generated docker image ID and run docker run -p 8080:8080 IMAGE_ID
, I'm able to access the GraphQL playground, but can't communicate with the MySQL container
If I change the network as such: docker run --network=host -p 8080:8080 IMAGE_ID
the Dockerized Go app can successfully communicate with the MySQL container, but then the GraphQL playground becomes inaccessible. The GraphQL playground only becomes accessible if I maintain --network=bridge
. I'm not sure why MySQL isn't using bridge
as well, since i never specified the network when starting it. This is how I got the MySQL container
docker run -p 3306:3306 --name my-db -e MYSQL_ROOT_PASSWORD=testing -d mysql:8.0.31
答案1
得分: 1
所以,你这里有几个问题:
首先,你很可能可以通过 docker exec -it container_name /bin/sh
访问没有安装 bash 的容器,因为大多数容器至少都带有 sh。
其次,你的主机每个端口只能有一个服务,所以当你将网络主机分配给一个容器时,会覆盖其他容器的端口映射,这就是为什么在使用网络主机启动 go 应用后,GraphQL 变得无法访问的原因,因为它们都使用端口 8080。
第三,当你使用默认的桥接网络时,你的容器只能通过 IP 进行通信,而不能通过容器名称进行通信。
此外,你不需要端口映射来让容器彼此通信。端口映射只在 Docker 网络之外的某些东西需要访问时才需要。
你最好的选择是使用 docker network create network_name
创建一个网络,然后通过 Docker 运行命令使用 --network network_name
将网络分配给所有容器。
你不一定需要端口映射来运行应用程序,但是当你想从外部访问服务时(例如主机的浏览器),请确保为每个容器使用唯一的端口。外部端口不必与容器的内部端口相同,你可以进行映射,例如 -p 8081:8080
。
由于所有容器都属于一个应用程序,你可能还想检查一下是否使用 Docker Compose 是更好的选择,因为它允许你通过一个配置文件轻松管理所有容器。
英文:
So, you have several problems here:
First of all, you can most likely access containers that don't have bash installed through docker exec -it container_name /bin/sh
, as most containers at least come with sh.
Second, your host machine can only have one service per port, so when you assign network host to a container, you overwrite the port mapping of other containers, which is why your GraphQL became unreachable after starting the go app with network host as a result of that they both use port 8080.
Third, when you use the default bridge network, your containers can only communicate by IP, not by container name.
Also, you don't need a port mapping to let the containers communicate with each other. Port mapping is only required, when something outside the Docker network needs the access.
Your best chance is to create a network with docker network create network_name
and then to assign the network to all containers with --network network_name
through the Docker run command.
You don't necessarily need a port mapping to get your application running, but when you want to access a service from outside - e.g. your hosts browser - make sure to take a unique port for each container. The port outside doesn't have to be the same as the container's internal port, you can map for instance -p 8081:8080
.
Since all containers belong to one app, you also might want to check whether docker compose is the better alternative as it allows you to easily manage all your container by one config file.
答案2
得分: 0
结果表明,我需要使用以下地址实际访问MySQL,因为Mac上的Docker使用Linux虚拟机:
docker.for.mac.localhost:3306
英文:
the answer was here:
https://stackoverflow.com/questions/52504318/unable-to-connect-to-mysql-server-with-go-and-docker-dial-tcp-127-0-0-13306
turns out i need to actually access MySQL using the following address, since Docker on Mac uses Linux VM:
docker.for.mac.localhost:3306
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论