Docker-compose
网址 | 备注 |
---|---|
优秀示例 |
安装
Windows和Mac在默认安装了docker desktop以后,docker-compose随之自动安装.
Linux用户需要自行安装
直接安装:
sh
# version=v2.27.1
$ sudo curl -L "https://github.com/docker/compose/releases/download/<version>/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
pip去安装docker-Compose:
sh
$ pip install docker-compose
语法
基本语法
yaml
version: "3.8"
services: # 一个或者多个容器
servicename: # 服务名字,这个名字也是内部 bridge网络可以使用的 DNS name
container_name: new-container-name # 容器名字,默认为服务名字,同时会忽略项目名字和数字
image: # 镜像的名字
command: # 可选,如果设置,则会覆盖默认镜像里的 CMD命令
environment: # 可选,相当于 docker run里的 --env
volumes: # 可选,相当于docker run里的 -v
networks: # 可选,相当于 docker run里的 --network
ports: # 可选,相当于 docker run里的 -p
servicename2:
volumes: # 可选,相当于 docker volume create
networks: # 可选,相当于 docker network create
示例:
app.py
python
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
Dockerfile:
dockerfile
FROM python:3.9.5-slim
RUN pip install flask redis && \
groupadd -r flask && useradd -r -g flask flask && \
mkdir /src && \
chown -R flask:flask /src
USER flask
COPY app.py /src/app.py
WORKDIR /src
ENV FLASK_APP=app.py REDIS_HOST=redis
EXPOSE 5000
CMD ["flask", "run", "-h", "0.0.0.0"]
docker-compose.yml 文件如下
version 1
yaml
version: '3.8'
services:
redis-server:
image: redis:latest
networks:
- demo-network
flask-demo:
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
networks:
- demo-network
ports:
- 8080:5000
networks:
demo-network:
version 2
yaml
version: '3.8'
services:
redis-server:
image: redis:latest
networks:
- demo-network
flask-demo:
container_name: my-flask-demo
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
networks:
- demo-network
ports:
- 8080:5000
networks:
demo-network:
Version 3
yaml
version: '3.8'
services:
redis-server:
image: redis:latest
networks:
- demo-network
flask-demo:
build: './flask'
container_name: my-flask-demo
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
networks:
- demo-network
ports:
- 8080:5000
networks:
demo-network:
Version 4
yaml
version: '3.8'
services:
redis-server:
image: redis:latest
networks:
- demo-network
flask-demo:
build:
context: ./flask
dockerfile: Dockerfile
container_name: my-flask-demo
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
networks:
- demo-network
ports:
- 8080:5000
networks:
demo-network:
启动
sh
# 前台服务运行
docker-compose up
# 后台运行
docker-compose up -d
# rebuild
docker-compose up -d --build
# remove not used
docker-compose up -d --remove-orphans --build
# 重启服务
docker-compose restart
# 停止服务
docker-compose stop
# 移除并停止服务
docker-compose down
# 移除停止的服务
docker-compose rm
# docker-compose 启动的服务,默认会加上文件夹的名字作为前缀,也可以通过 -p 指定服务名称前缀,并且以后所有相关操作都需要加 -p 选项
docker-composer -p myproject up -d
# 查看变量的真实值,默认是.env,自定义的env需紧跟docker-compose后,包括config, up 命令全是需要要紧跟
docker-compose --env-file ./myenv config
网络
yaml
version: '3.8'
services:
box1:
image: xiaopeng163/net-box:latest
command: /bin/sh -c "while true; do sleep 3600; done"
networks:
- mynetwork1
box2:
image: xiaopeng163/net-box:latest
command: /bin/sh -c "while true; do sleep 3600; done"
networks:
- mynetwork1
- mynetwork2
networks:
mynetwork1:
mynetwork2:
水平扩展
docker-compose.yaml
yaml
version: '3.8'
services:
flask:
build:
context: ./flask
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
redis-server:
image: redis:latest
client:
image: xiaopeng163/net-box:latest
command: sh -c "while true; do sleep 3600; done;"
测试
sh
# scale, load balance
docker-compose up -d --scale flask=3
# cut short
docker-compose up -d --scale flask=1
Nginx
docker-compose.yml
yaml
version: "3.8"
services:
flask:
build:
context: ./flask
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
networks:
- backend
- frontend
redis-server:
image: redis:latest
networks:
- backend
nginx:
image: nginx:stable-alpine
ports:
- 8000:80
depends_on:
- flask
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro # read only
- ./var/log/nginx:/var/log/nginx
networks:
- frontend
networks:
backend:
frontend:
nginx.conf:
nginx
server {
listen 80 default_server;
location / {
proxy_pass http://flask:5000;
}
}
测试同上,注意重启nginx docker-compose restart nginx
。
环境变量
app.py
py
from flask import Flask
from redis import StrictRedis
import os
import socket
app = Flask(__name__)
redis = StrictRedis(host=os.environ.get('REDIS_HOST', '127.0.0.1'),
port=6379, password=os.environ.get('REDIS_PASS'))
@app.route('/')
def hello():
redis.incr('hits')
return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
docker-compose.yml
yaml
version: "3.8"
services:
flask:
build:
context: ./flask
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
- REDIS_PASS=${REDIS_PASSWORD}
networks:
- backend
- frontend
redis-server:
image: redis:latest
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
- backend
nginx:
image: nginx:stable-alpine
ports:
- 8000:80
depends_on:
- flask
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./var/log/nginx:/var/log/nginx
networks:
- frontend
networks:
backend:
frontend:
其它文件nginx同上。
服务依赖和健康检查
简易演示
Dockerfile:
dockerfile
FROM python:3.9.5-slim
RUN pip install flask redis && \
apt-get update && \
apt-get install -y curl && \
groupadd -r flask && useradd -r -g flask flask && \
mkdir /src && \
chown -R flask:flask /src
USER flask
COPY app.py /src/app.py
WORKDIR /src
ENV FLASK=app.py REDIS_HOST=redis
EXPOSE 5000
HEALTHCHECK --interval=30s \
--timeout=3s \
CMD curl -f http://localhost:5000 || exit 1
CMD ["flask", "run", "-h", "0.0.0.0"]
app.py:
py
from flask import Flask
from redis import StrictRedis
import os
import socket
app = Flask(__name__)
redis = StrictRedis(host=os.environ.get('REDIS_HOST', '127.0.0.1'),
port=6379, password=os.environ.get('REDIS_PASS'))
@app.route('/')
def hello():
redis.incr('hits')
return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
相关命令
sh
# 启动容器
docker container run -d --network mybridge --env REDIS_PASS=abc123 flask-demo
# 检查容器检查过程
docker container inspect 70
完全演示
yaml
version: '3.8'
services:
flask:
build:
context: ./flask
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
- REDIS_PASS=${REDIS_PASSWORD}
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:5000']
interval: 30s
timeout: 3s
retries: 3
start_period: 40s
depends_on:
redis-server:
condition: service_healthy
networks:
- backend
- frontend
redis-server:
image: redis:latest
command: redis-server --requirepass ${REDIS_PASSWORD}
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 1s
timeout: 3s
retries: 10
networks:
- backend
nginx:
image: nginx:stable-alpine
ports:
- 8000:80
depends_on:
flask:
condition: service_healthy
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./var/log/nginx:/var/log/nginx
networks:
- frontend
networks:
backend:
frontend:
相关命令
sh
# 启动容器
docker-compose up -d