docker network
引子
https://github.com/fanqingsong/fastapi-react-postgres-keycloak-sso
docker compose 配置文件定义了若干service
version: "3"
services:
nginx:
image: nginx:1.17
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./logs/nginx:/var/log/nginx
ports:
- 80:80
depends_on:
- frontend
- backend
backend:
restart: unless-stopped
build:
context: backend
dockerfile: Dockerfile
env_file:
- .env
environment:
PYTHONPATH: .
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_USER}
volumes:
- ./logs/backend:/logs
ports:
- 8888:8888
depends_on:
- postgres
- keycloak
frontend:
build:
context: frontend
dockerfile: Dockerfile
ports:
- 8000:8000
environment:
NODE_ENV: development
CHOKIDAR_USEPOLLING: "true"
keycloak:
image: jboss/keycloak:12.0.4
environment:
DB_VENDOR: POSTGRES
DB_SCHEMA: public
DB_ADDR: keycloak_postgres
DB_DATABASE: ${KEYCLOAK_DB_DATABASE}
DB_USER: ${KEYCLOAK_DB_USER}
DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
KEYCLOAK_USER: ${KEYCLOAK_ADMIN_USERNAME}
KEYCLOAK_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
JDBC_PARAMS: "useSSL=false"
ports:
- 8080:8080
depends_on:
- keycloak_postgres
postgres:
image: postgres
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- 5432:5432
volumes:
- postgres_data:/var/lib/postgresql/data
keycloak_postgres:
image: postgres
volumes:
- keycloak_postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${KEYCLOAK_DB_DATABASE}
POSTGRES_USER: ${KEYCLOAK_DB_USER}
POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
volumes:
postgres_data:
keycloak_postgres_data:
nginx反向代理可以直接使用service的名称做代理转发
一般网络访问使用域名或者IP访问网络资源,
什么机制可以支撑使用服务名来访问容器资源?
需要从docker的网络机制说起。
server {
listen 80;
listen [::]:80;
server_name _;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://frontend:8000;
access_log /var/log/nginx/access_frontend.log;
error_log /var/log/nginx/error_frontend.log;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api {
access_log /var/log/nginx/access_backend.log;
error_log /var/log/nginx/error_backend.log;
proxy_pass http://backend:8888/api;
}
}
docker network
https://docs.docker.com/network/
最常使用的三种网络类型
bridge -- 支持单机上的容器互相访问
host -- 支持容器直击使用主机的网络资源, port+IP
overlay -- 支持跨主机的分布式容器互相访问
Network drivers
Docker’s networking subsystem is pluggable, using drivers. Several drivers exist by default, and provide core networking functionality:
bridge: The default network driver. If you don’t specify a driver, this is the type of network you are creating. Bridge networks are usually used when your applications run in standalone containers that need to communicate. See bridge networks.
host: For standalone containers, remove network isolation between the container and the Docker host, and use the host’s networking directly. See use the host network.
overlay: Overlay networks connect multiple Docker daemons together and enable swarm services to communicate with each other. You can also use overlay networks to facilitate communication between a swarm service and a standalone container, or between two standalone containers on different Docker daemons. This strategy removes the need to do OS-level routing between these containers. See overlay networks.
bridge tutorial
https://docs.docker.com/network/network-tutorial-standalone/
host tutorial
https://docs.docker.com/network/network-tutorial-host/
overlay tutorial
https://docs.docker.com/network/network-tutorial-overlay/
networking practice on docker
https://docs.docker.com/get-started/07_multi_container/
Multi container apps
Up to this point, you’ve been working with single container apps. But, now you will add MySQL to the application stack. The following question often arises - “Where will MySQL run? Install it in the same container or run it separately?” In general, each container should do one thing and do it well. The following are a few reasons to run the container separately:
- There’s a good chance you’d have to scale APIs and front-ends differently than databases.
- Separate containers let you version and update versions in isolation.
- While you may use a container for the database locally, you may want to use a managed service for the database in production. You don’t want to ship your database engine with your app then.
- Running multiple processes will require a process manager (the container only starts one process), which adds complexity to container startup/shutdown.
And there are more reasons. So, like the following diagram, it’s best to run your app in multiple containers.
networking on compose
https://docs.docker.com/compose/networking/
与前节对比, compose就是对docker 网络原语的封装。
如果没有指定网络, 则会创建默认bridge网络,所有的业务的容器工作在此默认网络中
For example, suppose your app is in a directory called
myapp, and yourdocker-compose.ymllooks like this:services: web: build: . ports: - "8000:8000" db: image: postgres ports: - "8001:5432"When you run
docker compose up, the following happens:
- A network called
myapp_defaultis created.- A container is created using
web’s configuration. It joins the networkmyapp_defaultunder the nameweb.- A container is created using
db’s configuration. It joins the networkmyapp_defaultunder the namedb.Each container can now look up the hostname
webordband get back the appropriate container’s IP address. For example,web’s application code could connect to the URLpostgres://db:5432and start using the Postgres database.It is important to note the distinction between
HOST_PORTandCONTAINER_PORT. In the above example, fordb, theHOST_PORTis8001and the container port is5432(postgres default). Networked service-to-service communication uses theCONTAINER_PORT. WhenHOST_PORTis defined, the service is accessible outside the swarm as well.Within the
webcontainer, your connection string todbwould look likepostgres://db:5432, and from the host machine, the connection string would look likepostgres://{DOCKER_IP}:8001for examplepostgres://localhost:8001if your container is running locally.
也可以做更细的网络划分
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
# Use a custom driver
driver: custom-driver-1
backend:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"


浙公网安备 33010602011771号