1 | 算术运算符 |
shell 条件测试
1 | # 条件测试 |
Flex布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style type="text/css">
.box1 {
display: flex;
/*
开启flex布局 flex-container
主轴 main axis
交叉轴 cross axis
*/
/* flex-direction: column-reverse; */
/*
flex-direction 决定主轴的方向 默认值row 从左到右
row-reverse 从右到左
column 列 从上往下
column-reverse 列 从下往上
*/
/* justify-content:space-around; */
/*
justify-content 决定flex items 在主轴对齐方式
默认对齐方式 flex-start 与main start 对齐
flex-end 与main end 对齐
center 居中对齐
space-between flex items 之间等距离 与main start main end 两端对齐
space-evenly flex items 之间等距离 flex items main start main end 等距离
space-around flex items 之间等距离 flex items main start main end 距离是flex items 之间距离一半
*/
/* align-items: baseline; */
/*
justify-content 决定flex items 在交叉轴对齐方式
默认值 normal 弹性布局与stretch 一样
stretch flex items 在cross axis 方向的 size 为auto时 自动拉伸填充flex container
flex-start 与cross start 对齐
flex-end 与cross end 对齐
center 居中对齐
baseline 基线对齐
*/
/* flex-wrap: wrap-reverse; */
/*
默认所有flex items 都会在一行显示
flex-wrap 决定flex container 是单行还是多行
默认值nowrap 单行
wrap 多行
wrap-reverse 多行 对比wrap cross sart与cross end 相反
*/
/* flex-flow: row wrap; */
/*
flex-flow 缩写属性 -> flex-direction flex-wrap
*/
/* align-content: space-evenly; */
/*
align-content 决定多行 flex items 在交叉轴 对齐方式
默认值 stretch 拉伸
flex-start
flex-end
center 居中对齐
space-between flex items 之间等距离 cross start cross end 两端对齐
space-evenly flex items 之间等距离 flex items cross start cross end 等距离
space-around flex items 之间等距离 flex items cross start cross end 距离是flex items 之间距离一半
*/
/*
总结:
flex-container
display flex/inline-flex 开启flex布局
flex-driection 决定主轴的方向
justify-content 决定主轴上flex-items对齐方式
align-items 决定在交叉轴flex-items对齐方式
flex-wrap 是否换行显示
flex-flow flex-driection flex-wrap 缩写
*/
/*
flex-items
order 决定flex items 排布顺序 越小排在前面
*/
width: 500px;
height: 400px;
margin: 0 auto;
background-color: #ff00ff;
}
.item {
width: 100px;
height: 100px;
color:#fff;
text-align: center;
line-height: 100px;
}
.item1 {
background-color:red;
/* height: 60px; */
}
.item2 {
background-color:green;
/* height: 120px; */
}
.item3 {
background-color:blue;
/* height: 150px; */
}
</style>
<title>Flex布局</title>
</head>
<body>
<div class="box1">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
<strong>测试元素</strong>
</body>
</html>
一键搭建MySQL主从
已完成
- 一键安装mysql
- 一键安装ansible
- 一键配置主从
- 支持一主一从
- 支持一主多从
未完成
集成控制系统
- 显示主从状态
- 显示当前服务器负载情况
- 管理mysql数据库(赠删改查
- 在线编辑mysql配置文件
详细代码
1 | !/bin/bash |
了解iptables
特点
运行内核上,不需要启动进程
功能
- filter 过滤
- nat 地址转换
- mangle 拆解报文 修改 再封装
- raw 关闭nat表连接追踪功能
链
- prerouting 路由前
- input 到达本机内部的报文必经之路
- forward 由本机转发的报文必经之路
- output 由本机发出的报文必经之路
- postrouting 路由后
数据报文流程
- 流入 prerouting -> input
- 流出 output -> postrouting
- 转发 prerouting -> forward -> postrouting
总结 四表五链
- 四表 filter nat mangle raw
- 五链 prerouting input forward output postrouting
优先级
- prerouting raw –> mangle –> nat
- raw –> mangle –> nat –> filter (任意链执行优先级)
数据经过防火墙流程
| |
input ouput
(mangle --> [nat] --> filter) (raw --> mangle --> nat --> filter)
| |
入–> prerouting –> 路由判断 –> forward –> postrouting –>出
| | |
(raw –> mangle –> nat) (mangle –> nat) (mangle –> nat)
表和链的关系
- filter input forward output
- nat prerouting(snat) output postrouting(dnat) (centos7 还有input centos6没有)
- mangle prerouting input forward output postrouting
- raw prerouting output
匹配条件
基本匹配条件 source IP destination IP
扩展匹配条件 源端口 目标端口
处理动作
- ACCETP 允许数据包通过
- DROP 丢弃数据包
- REJECT 拒绝数据包
- SNAT 源地址转换
- MASQUERADE
- DNAT 目标地址转换
- REDIRECT 端口映射
- LOG /var/log/message 记录日志
命令详解
iptables -nvL
pkts 对应规则匹配到的报文数
bytes 对应规则匹配到的报文的大小总和
target 规则的动作
prot 协议
opt 规则对应选项
in 数据包由那个网卡流入
out 数据包由那个网卡流出
source 对应源地址 一个IP或IP段
destination 对应目标地址 一个IP或IP段
policy 表示某链默认策略
packets 默认策略匹配到包数量
bytes 默认策略匹配到包大小总和
查
1 | #-t默认参数filter -L 列出规则 |
增
1 | #增加 I行首插入 -s 源地址 |
删
1 | #指定行号删除 |
改
1 | #指定匹配条件要完整 |
保存
1 | service iptables save |
匹配条件
1 | #一次指定多个用逗号隔开 -s匹配源地址 -d匹配目标地址 |
扩展匹配条件
1 | #tcp --dport目标端口使用前需要先指定协议 如-p tcp -m tcp 指定对应扩展模块 |
自定义链
1 | #-N 新建一个链 |
动作 扩展动作
1 | #基本动作 |
具体命令
查(–line-numbers 显示行号)
iptables -t 表(默认filter) -nvL --line-numbers
增
iptables -I[A](insert append 插入 追加)
示例:
input链最后追加 (放行80端口)iptables -A INPUT -p tcp --dport 80 -j ACCEPT
input链第2行插入iptables -I INPUT 2 -p tcp --dport 80 -j ACCEPT
改
iptables -R INPUT 26 -p tcp --dport -j DROP
删
-D 链名 行号-D INPUT -s 118.126.103.41 -j ACCEPT
iptables -D INPUT 1
详细命令
-P 设置默认策略 iptables -P INPUT (DROP|ACCEPT)
-F 清空规则链
-L 查看规则链
-A(append) 在规则链末尾追加规则
-I(insert) num 在规则链第几行插入规则
-D(delete) num 删除某一行的规则
-s 匹配来源IP/MASK 可以通过!取反
-d 匹配目标地址 与-s用法相同
-i 网卡名称(eth0) 匹配指定网卡流入的数据
-o 网卡名称(eth0) 匹配指定网卡流出的数据
-p 匹配协议(tcp|udp|icmp)
--dport num 匹配目标端口号
--sport num 匹配来源端口号
-j 动作(ACCEPT|DROP|REJECT)
-m 扩展参数(state --state ESTABLISHED,RELATED)
坑
- 注意放行本地回环网卡 否则本地调用127.0.0.1有异常
iptables -A INPUT -i lo -j ACCEPT
网络知识总结
OSI七层模型
- 应用层 (具体应用 http ftp等协议)
- 表示层 (相互转换编码 高级语言<=>机器码)
- 会话层 (分流 是否通过网络转发出去)
- 传输层 (端口PORT(0-65535 16位2进制 0-1023 系统占用) 协议TCP(慢可靠性高) UDP(简单快可靠性差))
- 网络层 (网络地址 IP IP数据包 最大65535字节)
- 数据链路层 (mac地址 48位二进制 12位16进制 解读电信号0 1 同一局域网 广播方式 发送)
- 物理层 (传送0和1的电信号)
TCP建立链接
- A向B发送SYN(i)同步包
- B向A回复ACK(i+1)确认包并发送SYN(k)同步包
- A向B回复ACK(k+1)确认包
链接建立成功 三次握手
TCP断开链接
- A向B发送FIN(i)释放包
- B向A回复ACK(i+1)确认包
A不再向B发送数据 若B也不再向A发送数据 - B向A发送FIN(k)释放包
- A向B回复ACK(k+1)确认包
链接断开成功 四次挥手
TCP三次握手为啥需要四次挥手呢
tcp是全双工,需要确认双方都不传输数据才断开
TCP 11种状态
- CLOSED 初始状态 表示tcp连接关注着或未打开
- LISTEN 服务端启动socket处于监听状态 等待客户端连接
- SYN_RCVD 服务器接收客户端请求发来SYN报文
- SYN-SENT 客户端已发送SYN报文
- ESTABLISHED TCP连接已成功建立
- FIN_WAIT_1 等待对方发来FIN报文
- FIN_WAIT_2 等待对方发来FIN报文
- TIME_WAIT 收到了对方的FIN报文并发送ACK报文
- CLOSING 一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文
- CLOSE_WAIT 发送FIN报文给自己 应该回应一个ACK报文给对方
- LAST_ACK 当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候
SSL/TLS握手流程
- client向server发送client hello(生成随机数(client random)告诉server支持加密算法)
- server向client发送server hello(生成随机数(server random)并选择一个client支持加密算法并下发证书(公钥))
- client校验证书是否合法,合法再生成一个随机数(premaster secret)并用公钥加密发送给server
- server使用私钥获取client发来的随机数
- client和server根据之前约定的加密算法(对称加密),使用前面的三个随机数,生成”对话密钥”(session key),用来加密接下来的整个对话过程
Docker相关知识总结
Centos7安装Docker
卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
添加国内yum源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker CE
sudo yum makecache fast
sudo yum install docker-ce
启动Docker CE
sudo systemctl enable docker
sudo systemctl start docker
镜像加速
1 | cat /etc/docker/daemon.json |
Docker镜像
获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
运行
docker run -it --rm ubuntu:18.04 bash
- -it -i交互式操作 -t 终端
- –rm 退出时将其删除
- ubuntu:18.04 以ubuntu:18.04作为基础启动容器
- bash 启动后执行命令
列出镜像
docker image ls
镜像体积
docker system df
虚悬镜像
docker image prune
中间层镜像
docker image ls -a
列出部分镜像
docker image ls ubuntu
以特定格式显示
1 | #列出所有镜像ID |
- 删除本地镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
- 构建镜像(commit 慎用)
1 | #以nginx为基础镜像启动一个名为webserver的容器 映射80端口 |
- 用Dockerfile 定制镜像
Dockerfile是一个文本文件 包含一条条指令(Instruction)每条指令构建一层
1 | mkdir mynginx |
- 镜像构建上下文(Context)
1 | #构建在服务端由Docker引擎完成 构建时将指定路径下内容打包 上传给Docker引擎 然后展开构建 |
- docker build 用法
1 | #Git repo 进行构建 |
Dockerfile 指令详解
COPY 复制文件
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
- 例子
COPY package.json /usr/src/app/
COPY home.txt /mydir/
COPY --chown=555:mygroup files* /mydir/
ADD 高级复制文件
1
2#复制压缩包会自动解压
ADD test.tar.gz /- CMD 容器启动命令
CMD <命令>
CMD ["可执行文件", "参数1", "参数2"...]
- 例子
CMD echo $HOME
CMD ["nginx", "-g", "daemon off;"]
- 例子
- ENTRYPOINT 入口点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#1、场景一 带参数
cat Dockerfile
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["curl", "-s", "https://ip.ropon.top"]
docker build -t myip .
#测试
docker run myip -i
docker run myip
#2、场景2 预处理
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]ENV 设置环境变量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
- 例子
1
2
3
4
5
6
7ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NOD
E_VERSION-linux-x64.tar.xz" && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS25
6.txt.asc" && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.tx
t.asc && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.t
xt | sha256sum -c - && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/loc
al --strip-components=1 && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt && ln -s /usr/local/bin/node/usr/local/bin/nodejsARG 构建参数
ARG <参数名>[=<默认值>]
VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
- 例子
#向/data 写入信息不会记录容器存储层 VOLUME /data
- 例子
EXPOSE 声明端口
EXPOSE <端口1> [<端口2>...]
WORKDIR 指定工作目录
WORKDIR <工作目录路径>
USER 指定当前用户
USER <用户名>[:<用户组>]
- 例子
1
2
3RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]- HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD <命令>
- 例子
1
2
3
4
5
6
7
8FROM ubuntu:18.04
RUN apt-get update && apt-get install -y nginx curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
#启动容器测试
docker run -d --name web -p 80:80 nginx:V4
#查看健康状态
docker inspect --format '{{json .State.Health}}' web | python -m json.toolONBUILD 为了定制当前镜像而准备
ONBUILD <其它指令>
例子
1
2
3
4
5
6
7FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]多阶段构建镜像
1 | FROM scratch |
Docker容器
启动容器
docker run
- 新建并启动
1
2
3
4#新建一个容器
docker run ubuntu:18.04 /bin/echo "hello world"
#新建一个容器启动一个终端 用于交互
docker run -t -i ubuntu:18.04 /bin/bash- 启动已终止容器
docker container start
- 后台运行
docker run -d
终止容器
docker container stop
进入容器
使用-d 参数时 容器启动后回进入后台 可使用docker attach 或 docker exec(exit退出时容器不会因此停止)
导出和导入容器
- 导出容器
docker export 7691a814370e > ubuntu.tar
- 导入容器
cat ubuntu.tar | docker import - test/ubuntu:v1.0
- 导出容器
删除容器
docker container rm 或docker rm 强制删除-f
docker container prune 清理所有终止容器
拉取镜像
docker search centos 搜索镜像
docker pull ansible/centos7-ansible 拉取镜像
私有仓库
1 | #安装运行docker-registry |
- 私有仓库上传、搜索、下载镜像
1 | #标记镜像 |
Docker数据管理
- 数据卷
docker volume create my-vol 创建一个数据卷
docker run -P -it --name web --mount source=my-vol,target=/webapp ubuntu:18.04 /bin/bash 启动一个挂载数据卷的容器
docker inspect web 查看数据卷的具体信息
docker volume rm my-vol 删除数据卷
docker volume prune 去拿过来无主的数据卷
- 挂载主机目录
docker run -it --name web --mount type=bind,source=/home/docker,target=/webapp ubuntu:18.04 /bin/bash
默认读写 可--mount type=bind,source=/home/docker,target=/webapp,readonly 配置只读
- 应用
1 | #记录容器内的操作日志 |
Docker 网络
外部访问容器
-p 指定端口映射 -p 8080:80 -P会随机映射一个49000~49900
映射所有接口地址
-p 5000:5000
映射到指定地址的指定端口
-p 127.0.0.1:5000:5000
映射指定地址的任意端口
-p 127.0.0.1::5000
-p 127.0.0.1:5000:5000/udp 标记指定udp端口
查看映射端口配置
docker port nostalgic_morse 5000
容器互联
新建网络
docker network create -d bridge my-net
连接容器
docker run -it --rm --name test01 --network my-net centos:7 /bin/bash
docker run -it --rm --name test02 --network my-net centos:7 /bin/bash
配置 DNS
1
2
3
4
5
6
7
8
9
10
11
12
13
14cat /etc/docker/daemon.json
"dns": [
"119.29.29.29".
"114.114.114.114"
]
#设置主机名
-h name
docker run -h testname
#设置dns
--dns=119.29.29.29
docker run --dns=119.29.29.29
#配置dns搜索域
--dns-search=west.cn
docker run --dns-search=west.cn高级网络配置
1
2docker启动时 --> 会在主机自动创建一个docker0虚拟网桥(bridge 软件交换机)
一端eth0 另外一端是vethXXXX快速配置指南
1
2
3
4
5
6
7
8
9
10
11
12
13
14-b 指定容器挂载的网桥
--bip=CIDR 定制docker0的掩码
-H SOCKET docker服务端接收命令的通道
--icc=true|false 是否支持容器间通信
--ip-forward=true|false
--iptables=true|false 是否运行docker添加iptables规则
--mtu=BYTES 容器网络中MTU
--dns=223.5.5.5
--dns-search=west.cn
-h hostname
--link=CONTAINER_NAME:ALIAS 添加到另外一个容器的连接
--net=bridge|none|container:NAME_OR_ID|host 配置容器桥接模式
-p SEPC 映射容器端口到宿主主机
-P 映射容器所有端口到宿主主机容器访问控制
1
2
3
4
5
6
7
8
9
10#容器访问外部网络
#打开系统转发
cat /etc/sysctl.conf
net.ipv4.ip_forward=1
#容器之间访问
#所有容器都会被连接到docker0网桥上
#本地系统防火墙是否运行通过
#访问所有端口
默认情况下,不同容器之间是允许网络互通
为了安全,可在/etc/docker/daemon.json配置"icc": false访问指定端口
1
2-icc=false 关闭网络访问后 还可通过 --link=CONTAINER_NAME:ALIAS 访问容器开放端口
配置docker0网桥
1
docker服务默认会创建一个docker0网桥 还给docker0网桥设置IP地址和子网掩码
自定义网桥
1
2
3
4
5
6
7
8
9
10
11#删除旧网桥
yum install -y bridge-utils
systemctl stop docker
ip link set dev docker0 down
brctl delbr docker0
#创建一个网桥
brctl addbr bridge0
ip addr add 192.168.5.1/24 dev bridge0
ip link set dev bridge0 up
#在/etc/docker/daemon.json配置
"bridge": "bridge0"
Compose
- 安装
yum install -y docker-compose
- 例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32mkdir -p /root/mypython
cd /root/mypython
cat app.py
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
cat Dockerfile
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
cat docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
#运行compose项目
docker-compose up - 命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#命令选项
-f 指定使用的compose模板文件 默认docker-compose.yml
-p 指定项目名称 默认使用目录名作为项目名称
--x-networking 使用docker的可插拔网络后端特性
--x-networking-driver DRIVER 指定网络后端的驱动 默认bridge
--verbose 输出更多调试信息
-v 打印版本并退出
#命令使用
build 构建项目中服务容器
--force-rm 删除构建过程中的临时容器
--no-cache 构建过程中不使用cache
--pull 始终尝试通过pull获取新版本的镜像
config 检查compose文件格式是否正确
down 停止up命令所启动的容器并移除网络
exec 进入指定的容器
images 列出compose文件中包含的镜像
kill -s参数指定发送的信号 docker-compose kill -s SIGINT 强制停止所有容器
logs 查看服务容器的输出
pause 暂停一个服务容器
port 输出某个容器端口锁映射的公共端口
ps 列出项目中目前所有容器 -q参数 只打印容器ID信息
pull 拉取服务依赖的镜像 --ignore-pull-failures 忽略拉取过程中的错误
push 推送服务依赖的镜像到docker镜像仓库
restart 重启项目中的服务
rm 删除所有服务容器
run 在指定服务商执行命令
scale 设置指定服务运行的容器个数 docker-compose scale web=3 db=2
start 启动已经存在的服务容器
stop 停止已经处于运行状态的容器
top 查看各个服务容器内的运行的进程
unpause 恢复暂停中的服务
up 自动完成包括构建镜像 创建服务 启动服务 - compose模板文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50build Dockerfile所在文件夹的路径
cap_add cap_drop 指定容器内核能力分配
#拥有所有能力
cap_add:
- ALL
#去掉NET_ADMIN能力
cap_drop:
- NET_ADMIN
command 覆盖容器启动后默认执行命令
command: echo "hello world"
configs 仅用于swarm mode
cgroup_parent 指定父cgroup 继承改组的资源限制
container_name 指定容器名称
deploy 仅用于swarm node
devices 指定设备映射关系
depends_on 解决容器依赖 启动先后
services:
web:
build: .
depends_on:
- db
- redis
dns 自定义dns
dns: 114.114.114.114
dns:
- 8.8.8.8
- 114.114.114.114
dns_search 配置dns搜索域
tmpfs 挂载一个tmpfs文件系统到容器
env_file 从文件中获取环境变量
environment 设置环境变量
expose 暴露端口 但不映射到宿主机
external_links
extra_hosts 指定额外的host名称映射信息
healthcheck 通过命令检查容器是否正常运行
image 指定镜像名称或镜像ID
labels 为容器添加元信息
logging 配置日志选项
network_mode 设置网络模式
networks 配置容器连接的网络
pid
ports 暴露端口信息
secrets 储存敏感数据
security_opt 配置标签的用户名和角色名
stop_signal 设置另外一个信号来停止容器
sysctls 配置容器内核参数
ulimits 指定容器的限制值
volumes 配置挂载数据卷 HOST:CONTAINER:ro
volumes:
- /var/lib/mysql/:ro - 例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19mkdir -p /root/mydjango
cd /root/mydjango
cat Dockerfile
FROM python:3.6-alpine
ENV PYTHONUNBUFFERED 1
WORKDIR /code
ADD . /code/
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
cat docker-compose.yml
version: '3'
services:
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8080
volumes:
- .:/code
ports:
- "8080:8080"
Docker Machine
- 安装
1
2
3curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine - 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22active 查看活跃的docker主机
config 输出连接的配置信息
create 创建一个docker主机
env 显示连接某主机需要的环境变量
inspect 获取主机更多信息
ip 获取主机地址
kill 停止某主机
ls 列出所有管理的主机
provision 重新设置一个已存在的主机
regenerate-certs 为某个主机重新生成TLS认证信息
restart 重启主机
rm 删除某台主机
ssh SSH到主机上执行命令
scp 在主机之间复制文件
mount 挂载主机目录到本地
start 启动主机
status 查看主机状态
stop 停止主机
upgrade 更新主机docker版本为最新
url 获取主机URL
version 输出docker-machine版本信息
help 输出帮助信息
Docker Swarm
Swarm 集群管理编排工具
docker swarm
初始化集群
1
2
3
4
5
6#初始化
docker swarm init --advertise-addr 172.16.7.127
#增加工作节点
docker swarm join --token xxxxxx 172.16.7.127:2377
#查看集群
docker node ls部署服务
1
2
3
4
5
6
7
8
9
10
11
12
13#新建服务
docker service create --replicas 3 -p 80:80 --name nginx nginx:V3
#查看服务
docker service ls
#查看某个服务的日志
docker service logs nginx
#服务伸缩
#增加
docker service scale nginx=8
#减少
docker service scale nginx=2
#删除服务
docker service rm nginxSwarm集群使用compose文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52version: '3'
services:
wordpress:
image: wordpress
ports:
- 80:80
networks:
- overlay
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
deploy:
mode: replicated
replicas: 3
db:
image: mysql
networks:
- overlay
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
deploy:
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- 8080:8080
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
volumes:
db-data:
networks:
overlay:
#部署服务
docker stack deploy -c docker-compose.yml wordpress
#查看服务
docker stack ls
#移除服务
docker stack down 服务名Swarm集群管理敏感数据
1
2
3
4#创建secret
openssl rand -base64 20 | docker secret create mysql_password -
#查看secret
docker secret ls创建MySQL服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27docker network create -d overlay mysql_private
docker service create \
--name mysql \
--replicas 1 \
--network mysql_private \
--mount type=volume,source=mydata,destination=/var/lib/mysql \
--secret source=mysql_root_password,target=mysql_root_password \
--secret source=mysql_password,target=mysql_password \
-e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
-e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
-e MYSQL_USER="wordpress" \
-e MYSQL_DATABASE="wordpress" \
mysql:latest
docker service create \
--name wordpress \
--replicas 1 \
--network mysql_private \
-p 3000:80 \
--mount type=volume,source=wpdata,destination=/var/www/html \
--secret source=mysql_password,target=wp_db_password,mode=0400 \
-e WORDPRESS_DB_USER="wordpress" \
-e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password"\
-e WORDPRESS_DB_HOST="mysql:3306" \
-e WORDPRESS_DB_NAME="wordpress" \
wordpress:latestSwarm集群中管理配置数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14#新建redis.conf文件
cat redis.conf
port 6380
#创建config
docker config create redis.conf redis.conf
#查看config
docker config ls
#创建redis服务
docker service create \
--name redis \
--config redis.conf \
-p 6379:6380 \
redis:latest \
redis-server /redis.confSwarm mode与滚动升级
1
2
3
4
5
6
7
8
9#之前已通过命令创建nginx服务
docker service create --name nginx --replicas 2 -p 80:80 nginx:1.13.7-alpine
#升级
docker service update \
--image nginx:1.13.12-alpine \
nginx
#回滚
docker service rollback nginxetcd集群
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47version: '3'
networks:
byfn:
services:
etcd1:
image: quay.io/coreos/etcd
container_name: etcd1
command: etcd -name etcd1 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- byfn
etcd2:
image: quay.io/coreos/etcd
container_name: etcd2
command: etcd -name etcd2 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- byfn
etcd3:
image: quay.io/coreos/etcd
container_name: etcd3
command: etcd -name etcd3 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- byfn
#查看集群状态
docker exec -t etcd1 etcdctl member list
#etcd操作
#set 设置值
etcdctl put /testdir/testkey "Hello world"
#put 更新值
etcdctl update /testdir/testkey "Hello world 666"
#get 获取值
etcdctl get /testdir/testkey
#更多命令可查--help
etcdctl --helpk8s
1
2
3#快速上手
#启动etcd服务
docker run --net=host -d gcr.io/google_containers/etcd:2.0.9 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data
Redis相关知识
Redis
redis中字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#设置值
set key val
#获取值
get key
#删除值
del key
#自增
INCR key-name
#自减
DECR key-name
#将存储值加上整数
INCRBY key-name amount
#将存储值减去整数
DECRBY key-name amount
#将存储值加上浮点数
INCRBYFLOAT key-name amount
#将值value追加到给定键key-name当前存储的值的末尾
APPEND key-name value
#获取从偏移量start至偏移量end范围内的子串
GETRANGE key-name start end
#将start偏移量开始的子串设置为给定值
SETRANGE key-name offset value
#将字节串看作二进制串 并返回字串中offset的二进制位的值
GETBIT key-name offset
#将字节串看作二进制串 并将字串中offset的二进制位的值设置为value
SETBIT key-name offset value
BITCOUNT key-name [start end]
BITTOP operation dest-key key-nameredis中的列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20LPUSH 将元素推入列表左端
lpush lstkey lval1
RPUSH 将元素推入列表右端
rpush lstkey rval1
LPOP 从列表左端弹出元素
lpush lstkey
RPOS 从列表右端弹出元素
rpush lstkey
LINDEX 获取列表在给定位置上的一个元素
lindex lstkey 1
LRANGE 获取列表在给定范围上的所有元素
lrange lstkey 0 2
LTRIM 对列表进行修剪 只保留start偏移量到end偏移量范围内的元素
ltrim lstkey 0 2
BLPOP 从非空列表中弹出位于最左端的元素
BRPOP 从非空列表中弹出位于最右端的元素
RPOPLPUSH
rpoplpush source-key dest-key
BRPOPLPUSH
brpoplpush source-key dest-keyredis的集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21SADD 将元素添加到集合
sadd setkey val22
SREM 从集合移除元素
srem setkey val22
SISMEMBER 检查集合中是否存在此元素
sismember setkey val22
SMEMBERS 获取集合中所有元素
smembers setkey
SCARD 获取集合包含元素的数量
scard setkey
SRANDMEMBER 从集合里面随机返回一个或多个元素
srandmember setkey 2
SPOP 随机从集合中移除一个元素 并返回被移除的元素
spop setkey
SMOVE 如果item存在source-key集合中 移除此元素添加到dest-key集合
smove source-key dest-key item
#额外还支持
SINTER 交集
SUNION 并集
SDIFF 差集redis的散列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20HSET 散列中关联给定的键值对
hset hashkey key1 val1
HGET 获取指定散列键的值
hget hashkey key1
HGETALL 获取散列中所有键值对
hgetall hashkey
HDEL 删除散列中指定键值对
hdel hashkey key1
HMSET 为散列里一个或多个键设置值
hmset hashkey key1 val1 key2 val2
HLEN 获取散列包含键值对的数量
hlen hashkey
HEXISTS 检查给定键是否存在于散列中
hexists hashkey key1
HKEYS 获取散列包含的所有键
hkeys hashkey
HVALS hashkey 获取散列包含的所有值
hvals hashkey
HINCRBYFLOAT 将key存储的值加上浮点数
hincrbyfloat hashkey key1 incrementredis的有序集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18ZADD 将一个给定分值的成员添加到有序集合
zadd zsetkey 90 zhansan
ZRANGE 从有序集合李获取多个元素
zrange zsetkey 0 2 withscores
ZRANGEBYSCORE 获取给定分值范围内的所有元素
zrangebyscore zsetkey 82 95 withscores
ZREM 移除成员
zrem zsetkey zhansan
ZCARD 获取有序集合包含成员的数量
zcard zsetkey
ZCOUNT 返回分值介于min和max之间的成员数量
zcount zsetkey 80 90
ZRANK 返回某个成员在集合中的排名
zrank zsetkey zhangsan
ZSCORE 返回某个成员的分值
zscore zsetkey lisi
ZINCRBY 将某个成员的分值加上increment
zincrby zsetkey 2 lisi案例:投票
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/6/5 11:17
# @Author : Ropon
# @File : test.py
import time, redis
pool = redis.ConnectionPool(host="172.16.7.127", port=6379, password="", max_connections=1024)
conn = redis.Redis(connection_pool=pool)
ONE_WEEK_IN_SECONDS = 7 * 86400
VOTE_SCORE = 200
def article_vote(conn, user, article):
"""
投票函数
"""
# 计算投票截止时间
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('time:', article) < cutoff:
return
article_id = article.split(':')[-1]
if conn.sadd('voted:' + article_id, user):
# ZINCRBY 对有序集合成员的分值执行自增
conn.zincrby('score:', article, VOTE_SCORE)
# HINCRBY 对散列存储的值进行自增
conn.hincrby(article, 'vote', 1)
def post_article(conn, user, title, link):
"""
新增文章函数
"""
# INCR 计数器自增
article_id = str(conn.incr('article:'))
voted = 'voted:' + article_id
conn.sadd(voted, user)
conn.expire(voted, ONE_WEEK_IN_SECONDS)
now = time.time()
article = 'article:' + article_id
conn.hmset(article, {
'title': title,
'link': link,
'poster': user,
'time': now,
'votes': 1,
})
conn.zadd('score:', {article: now + VOTE_SCORE})
conn.zadd('time:', {article: now})
return article_id
ARTICLES_PER_PAGE = 25
def get_articles(conn, page, order='score:'):
"""
获取所有文章
"""
start = (page - 1) * ARTICLES_PER_PAGE
end = start + ARTICLES_PER_PAGE - 1
ids = conn.zrevrange(order, start, end)
articles = []
for id in ids:
article_data = conn.hgetall(id)
article_data['id'] = id
articles.append(article_data)
return articles
def add_remove_groups(conn, article_id, to_add=None, to_remove=None):
"""
添加或删除分类
"""
if to_remove is None:
to_remove = []
if to_add is None:
to_add = []
article = 'article:' + article_id
for group in to_add:
conn.sadd('group:' + group, article)
for group in to_remove:
conn.srem('group:' + group, article)
def get_group_articles(conn, group, page, order='score:'):
"""
通过分类获取所有文章
"""
key = order + group
if not conn.exists(key):
conn.zinterstore(key, ['group:' + group, order], aggregate='max')
conn.expire(key, 60)
return get_articles(conn, page, key)
# post_article(conn, "Ropon", "Python从入门到放弃", "https://www.ropon.top/1.html")
article_vote(conn, "Ropon", "article:5")
kubernets知识点
- kubectl创建别名
1 | alias k=kubectl |
- tab补全命令
1 | yum install -y bash-completion |
- kubernets运行应用
1 | kubectl run kubia --image=luksa/kubia --port=8080 --generator=run/v1 |
- 创建一个服务
1 | #创建一个LoadBalancer服务 |
- 公共配置参数
1 | --log-backtrace-at traceLocation 记录日志每到 file:行号时打印一次stack trace 默认值0 |
- kube-apiserver 启动参数
1 | --admission-control strings 对发送给apiserver的任何请求进行准入控制 配置为一个准入控制器列表 |
Pod 资源文件详细说明
属性名称 | 取值类型 | 是否必需 | 取值说明 |
---|---|---|---|
version | String | yes | v1 |
kind | String | yes | Pod |
metadata | Object | yes | 元数据 |
metadata.name | String | yes | Pod的名称 |
metadata.namespace | String | yes | Pod所属名称空间 |
metadata.labels[] | List | 自定义标签列表 | |
metadata.annotation[] | List | 自定义注解列表 | |
spec | Object | yes | Pod中容器详细定义 |
spec.containers[] | List | yes | Pod中的容器列表 |
spec.containers[].name | String | yes | 容器的名称 |
spec.containers[].image | String | yes | 容器的镜像名称 |
spec.containers[].imagePullPolicy | String | 获取镜像策略 | |
spec.containers[].command[] | List | 容器启动命令列表 | |
spec.containers[].args[] | List | 启动命令参数列表 | |
spec.containers[].workingDir | String | 容器工作目录 | |
spec.containers[].volumeMounts[] | List | 容器存储卷配置 | |
spec.containers[].volumeMounts[].name | String | 共享存储卷名称 | |
spec.containers[].volumeMounts[].mountPath | String | 存储卷容器内挂载绝对路径 | |
spec.containers[].volumeMounts[].readOnly | Boolean | 是否只读模式,默认读写模式 | |
spec.containers[].ports[] | List | 容器暴露的端口号列表 | |
spec.containers[].ports[].name | String | 端口的名称 | |
spec.containers[].ports[].containerPort | Int | 容器需要监听的端口号 | |
spec.containers[].ports[].hostPort | Int | 默认与containerPort一致 | |
spec.containers[].ports[].protocol | String | 端口协议TCP UDP 默认TCP | |
spec.containers[].env[] | List | 容器需要环境变量列表 | |
spec.containers[].env[].name | String | 环境变量的名称 | |
spec.containers[].env[].value | String | 环境变量的值 | |
spec.containers[].resources | Object | 资源限制和资源请求设置 | |
spec.containers[].resources.limits | Object | 资源限制的设置 | |
spec.containers[].resources.limits.cpu | String | CPU限制 单位为core数 | |
spec.containers[].resources.limits.memory | String | 内存限制 单位MiB/GiB | |
spec.containers[].resources.requests | Object | 请求限制的设置 | |
spec.containers[].resources.requests.cpu | String | CPU请求 单位为core数 | |
spec.containers[].resources.requests.memory | String | 内存请求 单位MiB/GiB | |
spec.volumes[] | List | Pod定义共享存储卷列表 | |
spec.volumes[].name | String | 共享存储卷的名称 | |
spec.volumes[].emptyDir | Object | 与Pod同生命周期的临时目录 | |
spec.volumes[].hostPath | Object | Pod所在宿主机的目录 | |
spec.volumes[].hostPath.path | String | Pod所在在主机的目录 | |
spec.volumes[].secret | Object | 挂载预定义secret对象到容器 | |
spec.volumes[].configMap | Object | 挂载预定义configMap对象到容器 | |
spec.volumes[].livenessProbe | Object | 健康检查配置 | |
spec.volumes[].livenessProbe.exec | Object | 使用exec方式 | |
spec.volumes[].livenessProbe.exec.command[] | String | 指定命令或脚本 | |
spec.volumes[].livenessProbe.httpGet | Object | 使用httpGet方式 path prot | |
spec.volumes[].livenessProbe.tcpSocket | Object | 使用tcpSocket方式 | |
spec.volumes[].livenessProbe.initalDelaySeconds | Number | 启动后首次探测时间 单位s | |
spec.volumes[].livenessProbe.timeoutSeconds | Number | 探测超时时间 默认1s | |
spec.volumes[].livenessProbe.periodSeconds | Number | 探测时间间隔 默认10s | |
spec.restartPolicy | String | 重启策略 | |
spec.nodeSelector | Object | Pod调度到包含label的Node key:value格式指定 | |
spec.imagePullSecrets | Object | Pull镜像使用secret | |
spec.hostNetwork | Boolean | 是否使用主机网络模式 |
Pod 资源文件详细说明
属性名称 | 取值类型 | 是否必需 | 取值说明 |
---|---|---|---|
version | String | yes | v1 |
kind | String | yes | Pod |
metadata | Object | yes | 元数据 |
metadata.name | String | yes | Pod的名称 |
metadata.namespace | String | yes | Pod所属名称空间 |
metadata.labels[] | List | 自定义标签列表 | |
metadata.annotation[] | List | 自定义注解列表 | |
spec | Object | yes | Pod中容器详细定义 |
spec.selector[] | List | yes | 选择指定label标签的Pod |
spec.type | String | yes | service的类型默认ClusterIP |
spec.clusterIP | String | 虚拟服务IP地址 | |
spec.sessionAffinity | String | 是否支持session 默认为空 可选ClientIP 同一客户端到同一后端Pod | |
spec.ports[] | List | service需要暴露端口列表 | |
spec.ports[].name | String | 端口名称 | |
spec.ports[].protocol | String | 端口协议 TCP UDP 默认TCP | |
spec.ports[].port | int | 服务监听端口号 | |
spec.ports[].targetPort | int | 需要转发到后端Pod的端口号 | |
spec.ports[].nodePort | int | 当type=NodePort时 映射宿主机端口号 | |
status | object | 当type=LoadBalancer时 设置外部负载均衡器地址 | |
status.loadBalancer | object | 外部负载均衡器 | |
status.loadBalancer.ingress | object | 外部负载均衡器 | |
status.loadBalancer.ingress.ip | string | 外部负载均衡器的IP地址 | |
status.loadBalancer.ingress.hostname | string | 外部负载均衡器的主机名 |