文章目录
系统环境:Ubantu 20:04
1 安装docker-compose
root@dev-virtual-machine:/home/dev# sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 633 100 633 0 0 672 0 --:--:-- --:--:-- --:--:-- 672
100 12.1M 100 12.1M 0 0 4722k 0 0:00:02 0:00:02 --:--:-- 7857k
root@dev-virtual-machine:/home/dev# sudo chmod +x /usr/local/bin/docker-compose
root@dev-virtual-machine:/home/dev# sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
root@dev-virtual-machine:/home/dev# docker-compose --version
docker-compose version 1.29.2, build 5becea4c
2 YAML
YAML(Yet Another Markup Language) 是一种标记语言
2.1 基本语法
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许使用空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- “#”表示注释
2.2 数据类型
对象
键值对的集合,又称为映射(mapping)、哈希(hashes)、字典(dictionary)
对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格。
# 最普通
key: value
# 一个key多个子key
key:
childkey: value
childkey: value2
# 对象的属性是一个数组 [complexkey1,complexkey2],对应的值也是一个数组 [complexvalue1,complexvalue2]
?
- complexkey1
- complexkey2
:
- complexvalue1
- complexvalue2
数组
一组按次序排列的值,又称为序列(sequence)、列表(list)
# - 开头表示一个数组
-A
-B
-C
# 行内表示数组 ,使用中括号
key: [value1, value2, ...]
languages:
- Ruby
- Perl
- Python
websites:
YAML: yaml.org
Ruby: ruby-lang.org
Python: python.org
Perl: use.perl.org
转换成JSON
{
languages: [ 'Ruby', 'Perl', 'Python'],
websites: {
YAML: 'yaml.org',
Ruby: 'ruby-lang.org',
Python: 'python.org',
Perl: 'use.perl.org'
}
}
纯量(scalars)
单个的,不可再分的值
boolean:
- TRUE #true,True都可以
- FALSE #false,False都可以
float:
- 3.14
- 6.8523015e+5 #可以使用科学计数法
int:
- 123
- 0b1010_0111_0100_1010_1110 #二进制表示
null:
nodeName: 'node'
parent: ~ #使用~表示null
string:
- 哈哈
- 'Hello world' #可以使用双引号或者单引号包裹特殊字符
- newline
newline2 #字符串可以拆成多行,每一行会被转化成一个空格
date:
- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
- 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
2.3 锚点&和引用*
& 用来建立锚点(defaults),<< 表示合并到当前数据,* 用来引用锚点。
- &showell Steve
- Clark
- Brian
- Oren
- *showell
转为 JavaScript 代码如下:
[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]
3 自定义网络
创建一个网络用于自定义的服务,
创建网络的参数
root@dev-virtual-machine:/home/dev# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
创建网络的常规命令
docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
类型: 桥接 子网段 网关 网络名称
网络的详细信息
root@dev-virtual-machine:/home/dev# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "d76404cb8a115b87b589543bf39beff855eef254d615c19d3c49e2c7cf916eb7",
"Created": "2021-11-03T14:42:13.185097577+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/24",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
4 定义images
我们用一个很简单的例子,一个flask的镜像和一个redis的镜像,
4.1 redis镜像
docker pull redis:6.2 # 从dockerhub下载镜像
4.2 flask镜像
定义Dockerfile
FROM python:3.9-slim
MAINTAINER Zhao
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
CMD ["flask","run"]
打包镜像
docker build -t myweb:0.1 . # 标签后面的,(点号)不能漏了
查看当前的镜像
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myweb 0.1 4eb067c9317b 21 hours ago 147MB
python 3.9-slim ccd065bd50c5 8 days ago 122MB
redis 6.2 7faaec683238 3 weeks ago 113MB
5 编写yaml文件
yaml 文件
version: '3' # 版本号
services: # 服务
web01: # flask服务
image: "myweb:0.1" # 使用刚刚用Dockerfile制作好的镜像
ports: # 开放的端口
- "8081:8080"
depends_on: # 依赖,redis服务先启动,web服务后启动
- redis01
networks: # 使用自定义网络,方便用域名访问
- "mynet"
redis01: # redis服务
image: "redis:6.2" # 使用官方镜像
ports:
- "6380:6379" # 开放的端口
networks: # 使用自定义网络
- "mynet"
networks: # 因为使用自定义网络,所以需要配置mynet为自定义网络
mynet:
external: true
docker-compose 启动服务
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker-compose up -d
Creating myedgeapp_redis01_1 ... done
Creating myedgeapp_web01_1 ... done
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f154d8bdca05 myweb:0.1 "flask run" 31 seconds ago Up 31 seconds 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp myedgeapp_web01_1
762590b97831 redis:6.2 "docker-entrypoint.s…" 32 seconds ago Up 31 seconds 0.0.0.0:6380->6379/tcp, :::6380->6379/tcp myedgeapp_redis01_1
停止服务群
docker-compose stop
启动服务群
docker-compose start
docker-compose restart
停止并删除容器群
docker-compose down
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker-compose down
Stopping myedgeapp_web01_1 ... done
Stopping myedgeapp_redis01_1 ... done
Removing myedgeapp_web01_1 ... done
Removing myedgeapp_redis01_1 ... done
Network mynet is external, skipping
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@dev-virtual-machine:/home/dev/code/myedgeapp# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6(增) 项目文件目录
root@dev-virtual-machine:/home/dev/code/myedgeapp# ll
总用量 88888
drwxrwxrwx 4 root root 4096 11月 5 11:08 ./
drwxrwxrwx 6 dev dev 4096 11月 3 11:56 ../
-rwxrwxrwx 1 root root 413 11月 3 16:13 app.py*
-rw-r--r-- 1 root root 483 11月 3 17:07 docker-compose.yml
-rw-r--r-- 1 root root 225 11月 3 16:33 Dockerfile
-rwxrwxrwx 1 root root 100 11月 3 16:05 .flaskenv*
-rw-r--r-- 1 root root 12288 11月 3 15:09 .flaskenv.swp
-rw-r--r-- 1 root root 182 11月 3 16:05 Pipfile
-rw-r--r-- 1 root root 9180 11月 3 16:05 Pipfile.lock
-rw-r--r-- 1 root root 129 11月 3 16:15 requirements.txt
drwxr-xr-x 2 root root 4096 11月 3 15:01 templates/
drwxr-xr-x 5 root root 4096 11月 3 14:58 .venv/
6.1 requirements.txt文件详细
root@dev-virtual-machine:/home/dev/code/myedgeapp# cat requirements.txt
click==8.0.3
Flask==2.0.2
itsdangerous==2.0.1
Jinja2==3.0.2
MarkupSafe==2.0.1
python-dotenv==0.19.1
redis==3.5.3
Werkzeug==2.0.2
6.2 app.py文件详细
root@dev-virtual-machine:/home/dev/code/myedgeapp# cat app.py
from flask import Flask, render_template
from redis import StrictRedis
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
r= None
try:
r = StrictRedis(host='redis01',decode_responses=True)
if not r.get("k1"):
r.set("k1",0)
r.incr("k1")
return render_template('index.html', num = r.get("k1"))
finally:
r.close()
6.3 index.html文件详细
root@dev-virtual-machine:/home/dev/code/myedgeapp# cd templates/
root@dev-virtual-machine:/home/dev/code/myedgeapp/templates# ls
index.html
root@dev-virtual-machine:/home/dev/code/myedgeapp/templates# cat index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1> Count {{ num }} </h1>
</body>
- .flaskenv
FLASK_APP=app.py
FLASK_RUN_HOST=‘0.0.0.0’
FLASK_RUN_PORT=8080
FLASK_ENV=‘product’
app.py是单独模块,flaskenv在模块同级别目录下
app.py在包内,flaskenv在包同级别目录下