Docker Compose 通过 localhost 访问另一个容器
Docker Compose accessing another container via localhost
我正在思考如何访问其他容器 运行 作为 docker-compose
服务的一部分。
我看过很多关于在其他容器中通过服务名称访问容器的答案,但也有很多教程只是简单地使用具有公开端口的本地主机。
所以我只是想弄清楚什么时候使用哪个以及为什么它以这种方式工作。
我的示例应用程序是:https://github.com/daniil/full-stack-js-docker-tutorial
其中,我有一个将 ui 和 api 服务映射在一起的 NGINX 服务器,但事实上我意识到在我的 React 容器 (3000:3000) 内部我实际上可以只需向 http://localhost:5050
.
发出 axios 请求即可访问 Express 容器 (5050:5050)
但与此同时,如果我尝试通过本地主机连接到我的 MySQL 容器 (9906:3306),它不起作用,我必须使用 db
作为主机,即容器名称。
谁能帮我理解它是如何工作的:
- 我什么时候可以使用
http://localhost:SERVICE_PORT
,它在 React 服务中工作,因为它是一个浏览器请求吗?即:axios
- 为什么我不能在 React / axios 请求中使用
http://api:5050
,是因为没有主机解析吗?
- 为什么我不能使用
http://localhost:9906|3306
连接到我的数据库服务?
- NGINX 反向代理将客户端和 api 绑定在一起的目的或好处是什么,如果您实际上不需要介于两者之间,因为 localhost 似乎可以工作?
- 如果容器应该是隔离的,为什么我的 React 容器中的
localhost:5050
仍然在另一个容器中的 5050 上看到 API 服务器 运行?
- 可以帮助我理解跨容器通信如何工作的其他一般规则
这里的重要细节是您的 React 应用程序实际上并不 运行 在容器中。它在 Docker space 外部的最终用户浏览器中是 运行,因此无法访问 Docker 的内部网络。
假设您有一个典型的应用程序:
version: '3.8'
services:
frontend: { ... }
backend: { ... }
database: { ... }
proxy: { ... }
当一个容器直接调用另一个容器时使用Compose服务名称和服务的默认端口。 backend
容器可能配置为 database:5432
作为其数据库 URL; Nginx proxy
可能配置为 proxy_pass http://frontend:3000
。 ports:
不是必需的,如果存在则将被忽略。这 out-of-the-box 无需指定 networks:
或 container_name:
并且对于大多数简单的应用程序,您可以安全地省略这两个选项。
当浏览器应用程序调用容器时 使用主机的 DNS 名称或 IP 地址以及该容器的第一个 ports:
号码。
当浏览器应用程序调用容器时,并且您绝对肯定浏览器与容器位于同一主机上,仅在这种情况下,您可以使用http://localhost:12345
,再次匹配目标容器的第一个 ports:
编号。
What is the purpose or benefit of NGINX reverse proxy to tie client and api together?
避免实际需要知道主机名。假设你的 Nginx 配置看起来像
location / {
proxy_pass http://frontend:3000 ;
}
location /api {
proxy_pass http://backend:3000 ;
}
然后浏览器应用程序可以向 /api
发出 HTTP GET 请求,根本不需要知道服务器的主机名;它将使用与当前页面的 URL.
中相同的 hast 名称
这也意味着您可以避免直接发布其他涉及的容器,甚至可能有多个 back-end 个容器用于不同的目的。
完整但最小的设置可能如下所示:
version: '3.8'
services:
frontend:
build: ./frontend
backend:
build: ./backend
environment:
PGHOST: database
# PGUSER, PGPASSWORD
database:
image: 'postgres:14'
volumes:
- 'pgdata:/var/lib/postgresql/data'
environment: {} # POSTGRES_USER, POSTGRES_PASSWORD
proxy:
image: 'nginx:1.21'
volumes:
- './default.conf:/etc/nginx/conf.d/default.conf'
ports:
- '12345:80'
volumes:
pgdata:
使用上面显示的此设置和 Nginx 配置,浏览器调用 http://localhost:12345
将检索主应用程序。如果浏览器应用程序随后请求 /api/foo
,那将被转换为 http://localhost:12345/api/foo
,后者在 Docker space.
中被代理到 http://backend:3000/foo
我正在思考如何访问其他容器 运行 作为 docker-compose
服务的一部分。
我看过很多关于在其他容器中通过服务名称访问容器的答案,但也有很多教程只是简单地使用具有公开端口的本地主机。
所以我只是想弄清楚什么时候使用哪个以及为什么它以这种方式工作。
我的示例应用程序是:https://github.com/daniil/full-stack-js-docker-tutorial
其中,我有一个将 ui 和 api 服务映射在一起的 NGINX 服务器,但事实上我意识到在我的 React 容器 (3000:3000) 内部我实际上可以只需向 http://localhost:5050
.
但与此同时,如果我尝试通过本地主机连接到我的 MySQL 容器 (9906:3306),它不起作用,我必须使用 db
作为主机,即容器名称。
谁能帮我理解它是如何工作的:
- 我什么时候可以使用
http://localhost:SERVICE_PORT
,它在 React 服务中工作,因为它是一个浏览器请求吗?即:axios - 为什么我不能在 React / axios 请求中使用
http://api:5050
,是因为没有主机解析吗? - 为什么我不能使用
http://localhost:9906|3306
连接到我的数据库服务? - NGINX 反向代理将客户端和 api 绑定在一起的目的或好处是什么,如果您实际上不需要介于两者之间,因为 localhost 似乎可以工作?
- 如果容器应该是隔离的,为什么我的 React 容器中的
localhost:5050
仍然在另一个容器中的 5050 上看到 API 服务器 运行? - 可以帮助我理解跨容器通信如何工作的其他一般规则
这里的重要细节是您的 React 应用程序实际上并不 运行 在容器中。它在 Docker space 外部的最终用户浏览器中是 运行,因此无法访问 Docker 的内部网络。
假设您有一个典型的应用程序:
version: '3.8'
services:
frontend: { ... }
backend: { ... }
database: { ... }
proxy: { ... }
当一个容器直接调用另一个容器时使用Compose服务名称和服务的默认端口。 backend
容器可能配置为 database:5432
作为其数据库 URL; Nginx proxy
可能配置为 proxy_pass http://frontend:3000
。 ports:
不是必需的,如果存在则将被忽略。这 out-of-the-box 无需指定 networks:
或 container_name:
并且对于大多数简单的应用程序,您可以安全地省略这两个选项。
当浏览器应用程序调用容器时 使用主机的 DNS 名称或 IP 地址以及该容器的第一个 ports:
号码。
当浏览器应用程序调用容器时,并且您绝对肯定浏览器与容器位于同一主机上,仅在这种情况下,您可以使用http://localhost:12345
,再次匹配目标容器的第一个 ports:
编号。
What is the purpose or benefit of NGINX reverse proxy to tie client and api together?
避免实际需要知道主机名。假设你的 Nginx 配置看起来像
location / {
proxy_pass http://frontend:3000 ;
}
location /api {
proxy_pass http://backend:3000 ;
}
然后浏览器应用程序可以向 /api
发出 HTTP GET 请求,根本不需要知道服务器的主机名;它将使用与当前页面的 URL.
这也意味着您可以避免直接发布其他涉及的容器,甚至可能有多个 back-end 个容器用于不同的目的。
完整但最小的设置可能如下所示:
version: '3.8'
services:
frontend:
build: ./frontend
backend:
build: ./backend
environment:
PGHOST: database
# PGUSER, PGPASSWORD
database:
image: 'postgres:14'
volumes:
- 'pgdata:/var/lib/postgresql/data'
environment: {} # POSTGRES_USER, POSTGRES_PASSWORD
proxy:
image: 'nginx:1.21'
volumes:
- './default.conf:/etc/nginx/conf.d/default.conf'
ports:
- '12345:80'
volumes:
pgdata:
使用上面显示的此设置和 Nginx 配置,浏览器调用 http://localhost:12345
将检索主应用程序。如果浏览器应用程序随后请求 /api/foo
,那将被转换为 http://localhost:12345/api/foo
,后者在 Docker space.
http://backend:3000/foo