使用docker+uwsgi+nginx+mysql部署python-flask的web项目要求:实现负载均衡及高可用,并使用SSL证书来保证数据的安全传输,以及设置mysql主从复制。
简单的导图:
- 编写Dockerfile文件,设置基础镜像和安装依赖项,如Python、Flask、uwsgi、nginx等。
- 配置uwsgi与nginx。uwsgi是一个Web服务器,可以将Python应用程序与nginx一起使用,提供更好的性能和可扩展性。Nginx则是一个反向代理服务器,可以处理大量请求,并在uwsgi应用程序之间进行负载均衡。
- 使用Docker Compose编排应用程序。Docker Compose是一个用于定义和运行多容器Docker应用程序的工具,可以轻松地将uwsgi和nginx容器连接起来,并实现负载均衡和高可用性。使用Docker Compose也可以轻松地设置环境变量、网络和存储卷等。
- 使用容器编排工具,如Docker Swarm,实现高可用性。这些工具可以管理多个Docker容器,并确保应用程序的可用性。它们可以自动替换故障容器,并确保服务在多个节点上运行。
- 在MySQL中设置主从复制,实现数据库的高可用性。主从复制可以将MySQL数据库的写操作复制到多个从服务器上,提高了系统的可用性和性能。
web项目代码自取:
https://gitee.com/cwc188/docker.git
一、前期准备:
swarm集群规划:
机器名: | IP: | 角色: |
---|---|---|
docker_project | 192.168.18.130 | manager |
docker_project01 | 192.168.18.111 | worker |
docker_project02 | 192.168.18.112 | worker |
服务分布
服务: | uwsgi+flask | nginx | mysql-master | mysql-slave |
---|
1、自行配置yum源、安装docker,python,mysql等基础环境,安装docker-compose工具及安装部署docker-swarm集群的工作者与管理者节点
2、关闭防火墙、selinux等
3、将web项目代码解压至虚拟机目录下/opt/docker_file
(3台机器都需要有这个文件)
4、生成自签名“SSL证书”
①检查是否已经安装openssl:没有的自行yum安装
openssl version
②生成私钥
新建/opt/docker_file/app/cert
目录并进入,后执行命令:
openssl genrsa -des3 -out server.key 2048
#输入一个4位以上的密码。
③生成CSR(证书签名请求)
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=GUANGDONG/L=ZHAOQING/O=cwc/OU=cwc/CN=192.168.18.130/"
④去除私钥中的密码
openssl rsa -in server.key -out server.key
⑤生成自签名SSL证书
# -days 证书有效期-天
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
二、配置uwsgi
配置uwsgi.ini
新建文件/opt/docker_file/app/uwsgi.ini
编辑
[uwsgi]
module = app:app #运行的程序不用后缀的名称,通常是app
master = true #启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程
processes =4 #指定的工作进程的线程数量4个
chdir=/app #主程序的所在目录
#socket =/opt/douban_flask/myproject.sock #指定一个socker文件保存信息
socket =0.0.0.0:8080 #指定暴露的8080端口
logto =/app/myproject.log #日志输出地址
chmod-socket =660
vacuum = true #当服务器退出的时候自动删除unix socket文件和pid文件
buffer-size = 65535 # 设置用于uwsgi包解析的内部缓存区大小为128k。默认是4k
http-to-https = true #uWSGI容器内部的HTTP重定向到HTTPS
http-socket = 0.0.0.0:8080
三、配置nginx
创建新文件/opt/docker_file/app/nginx.conf
编辑
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
upstream flask {
server web:8080;
}
server {
listen 80;
listen 443 ssl;
ssl_certificate /app/cert/server.crt;
ssl_certificate_key /app/cert/server.key;
ssl_session_timeout 5m;#缓存有效期
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #加密算法
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #安全链接可选的加密协议
ssl_prefer_server_ciphers on #使用服务器端的首选算法
server_name _;
location /static {
alias /app/static;
}
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass flask;
}
}
}
四、编写dockerfile
生成python:v3.70
镜像,用于运行应用程序
vim /opt/docker_file/dockerfile
FROM python:v3.7
ADD /opt/docker_file/app/requirements.txt /app/
RUN python3 -m pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install uwsgi flask
WORKDIR /app
CMD ["uwsgi", "--ini", "uwsgi.ini"]
构建镜像
[root@docker_project app]# docker build python:v3.70 .
五、编写Docker-compose文件
version: '3'
services:
web:
image: python:v3.70
deploy:
replicas: 3
placement:
constraints: [node.role == worker]
expose:
- "8080"
volumes:
- /opt/docker_file/app/static:/app/static
- /opt/docker_file/app:/app
networks:
- webnet
nginx:
image: nginx:1.21
deploy:
replicas: 3
placement:
constraints: [node.role == worker]
volumes:
- /opt/docker_file/app/nginx.conf:/etc/nginx/nginx.conf
- /opt/docker_file/app/static:/app/static
- /opt/docker_file/app/cert/server.crt:/app/cert/server.crt
- /opt/docker_file/app/cert/server.key:/app/cert/server.key
ports:
- "1234:80"
- "443:443"
depends_on:
- web
networks:
- webnet
mysql-master:
image: mysql:5.7
deploy:
placement:
constraints: [node.role == manager]
replicas: 1
environment:
MYSQL_ROOT_PASSWORD: "1234567"
volumes:
- /path/to/mysql-master/data:/var/lib/mysql #自己创建
- /path/to/mysql-master/conf:/etc/mysql/conf.d #自己创建
command: ["mysqld", "--server-id=1", "--log-bin=mysql-bin", "--binlog-do-db=mydatabase"]
ports:
- "3307:3306"
networks:
- webnet
mysql-slave:
image: mysql:5.7
deploy:
placement:
constraints: [node.role == manager]
replicas: 1
environment:
MYSQL_ROOT_PASSWORD: "1234567"
volumes:
- /path/to/mysql-slave/data:/var/lib/mysql
- /path/to/mysql-slave/conf:/etc/mysql/conf.d
command: ["mysqld", "--server-id=2", "--log-bin=mysql-bin", "--binlog-do-db=mydatabase", "--relay-log=mysql-relay-bin", "--relay-log-info-repository=TABLE"]
ports:
- "3308:3306"
networks:
- webnet
networks:
webnet:
driver: overlay
运行docker-compose文件:
[root@docker_project docker_file]# docker stack deploy -c docker-compose-swarm.yml
解释:
server-id
:服务器 ID,必须在主服务器和从服务器上设置为唯一的值。主服务器的值应该大于从服务器的值。log-bin
:启用二进制日志记录。所有更改都将记录在二进制日志文件 中。mysql-bin
binlog-do-db
:指定要在二进制日志中记录的数据库。在此示例中,我们将 数据库记录到二进制日志中。mydatabase
binlog-ignore-db
:指定要从二进制日志中排除的数据库。在此示例中,我们将 数据库从二进制日志中排除。mysql
relay-log
:指定中继日志文件的名称。从服务器从主服务器接收二进制日志,并将其记录到中继日志文件中。log-slave-updates
:在从服务器上启用中继日志记录。这允许从服务器将接收到的二进制日志记录到它自己的二进制日志文件中。read-only
:将从服务器设置为只读模式,以防止意外更改。
六、配置MySql主从复制
进入主mysql容器
[root@docker_project docker_file]# mysql -uroot -p -P3304 -h192.168.18.130
#查看server_id是否生效
mysql> show variables like '%server_id%';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| server_id | 3 |
| server_id_bits | 32 |
+----------------+-------+
#看master信息 File 和 Position 从服务上要用
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 602 | mydatabase | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#开权限
mysql> grant replication slave,replication client on *.* to 'slave'@'%' identified by "1234567";
mysql> flush privileges;
查询mysql主数据库容器ip:
[root@docker_project app]# docker service inspect myswarm_mysql-master
进入从mysql服务
[root@docker_project docker_file]# mysql -uroot -p -P3305 -h192.168.18.130
#查看server_id是否生效
mysql> show variables like '%server_id%';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| server_id | 4 |
| server_id_bits | 32 |
+----------------+-------+
# 连接主mysql服务 master_log_file 和 master_log_pos的值要填写主master里查出来的值
change master to master_host='master的IP地址',master_user='slave',master_password='1234567',master_port=3306,master_log_file='mysql-bin.000004', master_log_pos=602,master_connect_retry=30;
#启动slave
mysql> start slave;
mysql> show slave status \G;
# 看到这两个个yes就代表成功了
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
设置从服务器slave为只读模式
在从服务器slave上操作
SHOW VARIABLES LIKE '%read_only%'; #查看只读状态
SET GLOBAL super_read_only=1; #super权限的用户只读状态 1.只读 0:可写
SET GLOBAL read_only=1; #普通权限用户读状态 1.只读 0:可写
在主数据库创建mydatabase数据库
从数据库也会自动创建,即代表主从复制成功。
create database mydatabase default charset utf8mb4 collate utf8mb4_general_ci;
执行pachon.py
程序将数据爬取并导入主数据库即可
访问http://192.168.18.130:1234或者https://192.168.18.130