概述

本文主要记录了在 Linux 3.10.0-1062.el7.x86_64 下使用 docker-compose 搭建服务的过程,由于公司服务器在内网中,搭建镜像及下载依赖时需要外部代理,如果本机服务无相关限制,可联通外网,配置代理部分忽略即可,其实 firewall 为开启,selinux 为 enforcing 状态。

部署中主要涉及以下内容:

  1. Nginx 代理 MySQL 和 django 服务以及 https 自签名的部署。
  2. 使用 gunicorn 部署 django 服务。
  3. MySQL 相关初始化配置,及建权过程。
  4. 将 .py 文件转为 .pyc 文件

Docker 安装

如果之前安装过的话,需要删除老版本 docker:

sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

安装构建 docker 所需要的工具;

 sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2

添加 docker 源:

sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

安装 docker ce:

sudo yum install docker-ce docker-ce-cli containerd.io

配置 docker:

sudo systemctl start docker
sudo systemctl enable docker

安装 docker-compose:

# download
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# apply exe permissions
sudo chmod +x /usr/local/bin/docker-compose
# add link
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# check
docker-compose --version

如果在安装中下无法下载相应服务,则表明可能需要配置相应代理或开放相关 ACL 配置,关于相关配置过程可参见Centos7 下代理配置

docker 的代理配置也需要单独做出来,可以参见docker 代理脱坑这篇。

项目结构

下面是 docker-compose 工程构建后完整目录:

├── config
│   ├── auto_start_script.sh
│   ├── mysql
│   │   ├── init
│   │   │   └── init.sql
│   │   ├── my.cnf
│   │   └── my.conf
│   ├── nginx
│   │   ├── conf.d
│   │   │   ├── certs
│   │   │   │   ├── cmi_sdn.crt
│   │   │   │   ├── cmi_sdn.key
│   │   │   │   └── dhparam.pem
│   │   │   ├── ssl.conf
│   │   │   └── ssl.conf.bk
│   │   ├── default.d
│   │   │   └── ssl-redirect.conf
│   │   ├── log
│   │   │   ├── access.log
│   │   │   └── error.log
│   │   └── nginx.conf
│   └── requirements.txt
├── docker-compose.yml
├── Dockerfile
├── db_storage # 创建文件夹就好,用于挂载 mysql 数据
└── project
├── your_project
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── static
└── frontend

tree -I '*project*|*frontend*|*db_storage*'

  • config 目录:存放 nginx 配置, requirement, mysql 配置
  • docker-compose.yml: 用于编排和管理容器的 yaml 文件
  • Dockerfile: 用于编写 django 镜像的文件
  • project:django 项目代码

Dockerfile 编写

编写 django 的运行环境,如不需要代理可将环境变量删除

FROM python:3.6.8

ENV MY_PROXY_URL="http://173.39.112.117:80"
ENV HTTP_PROXY=$MY_PROXY_URL \
HTTPS_PROXY=$MY_PROXY_URL \
FTP_PROXY=$MY_PROXY_URL \
http_proxy=$MY_PROXY_URL \
https_proxy=$MY_PROXY_URL \
ftp_proxy=$MY_PROXY_URL WORKDIR /src COPY /config/requirements.txt / RUN pip install --no-cache-dir -r /requirements.txt ENV MY_PROXY_URL=
ENV HTTP_PROXY=$MY_PROXY_URL \
HTTPS_PROXY=$MY_PROXY_URL \
FTP_PROXY=$MY_PROXY_URL \
http_proxy=$MY_PROXY_URL \
https_proxy=$MY_PROXY_URL \
ftp_proxy=$MY_PROXY_URL

创建 config/requirements.txt 文件,并添加所需要的 python 依赖包,部署选用 gunicorn. 文件如下:

Django==2.1.7
djangorestframework==3.9.2
djangorestframework-jwt==1.11.0
mysqlclient==1.4.2
PyJWT==1.7.1
requests==2.21.0
gunicorn==19.9.0
django-role-permissions==2.2.1
aiohttp==3.5.4
apscheduler==3.6.3
networkx==2.4
numpy==1.17.4

Nginx 配置

nginx/conf.d/certs 目录下,使用 openssl 进行自签名,生成需要的证书:

sudo openssl req   -x509   -nodes   -days 365   -newkey rsa:2048   -keyout example.key   -out example.crt;

sudo openssl dhparam -out dhparam.pem 2048

编写 nginx 配置文件 config/nginx/conf.d/ssl.conf

upstream web_server {
# ip_hash;
server web:8000 fail_timeout=100s;
#server 10.89.200.40:8000 backup;
keepalive 300;
} upstream topo {
# ip_hash;
server topo:7777 fail_timeout=100s;
#server 10.89.200.40:8000 backup;
keepalive 300;
} server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl; server_name server_IP_address; ssl_certificate /etc/nginx/conf.d/certs/cmi_sdn.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/cmi_sdn.key;
ssl_dhparam /etc/nginx/conf.d/certs/dhparam.pem;
########################################################################
# from https://cipherli.st/ #
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
######################################################################## ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff; ##################################
# END https://cipherli.st/ BLOCK #
################################## location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://web_server/;
proxy_connect_timeout 159s;
proxy_send_timeout 600;
proxy_read_timeout 600;
keepalive_timeout 600s;
} listen 8000;
server_name localhost; location /static {
autoindex on;
alias /src/static;
}
} server {
listen 666 http2 ssl;
listen [::]:666 http2 ssl; server_name server_IP_address; ssl_certificate /etc/nginx/conf.d/certs/cmi_sdn.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/cmi_sdn.key;
ssl_dhparam /etc/nginx/conf.d/certs/dhparam.pem;
########################################################################
# from https://cipherli.st/ #
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
######################################################################## ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
#add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff; ##################################
# END https://cipherli.st/ BLOCK #
################################## add_header X-Frame-Options sameorigin always; location = / {
root /src/frontend/dist;
index index.html index.htm;
} location ^~ /index.html {
root /src/frontend/dist;
index index.html index.htm; } location ^~ /favicon.png {
root /src/frontend/dist;
} location ^~ /static {
alias /src/frontend/dist/static;
} location ^~ /topo/get_topology/ {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://topo;
} location ^~ /topo/update_topology/ {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://topo;
} location ~* /.* {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://web_server;
proxy_connect_timeout 159s;
proxy_send_timeout 600;
proxy_read_timeout 600;
keepalive_timeout 600s;
} server_name localhost;
}

注意这里的 web 是 docker-compose 编排中的 django 所在容器名称。

topo 是我这里启用的另一服务,忽略即可。

编写 default.d/ssl-redirect.conf 添加 http 到 https 的自动跳转

return 301 https://$host$request_uri/;

编写 config/nginx/nginx.conf 配置入口文件

user  nginx;
worker_processes 1; error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid; events {
worker_connections 1024;
} http {
include /etc/nginx/mime.types;
default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on;
#tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf;
} stream {
# log_format main 'mysql - $remote_addr - [$time_local] ';
# access_log /var/log/nginx/access.log main; upstream mysql {
# hash $remote_addr consistent;
server 10.124.207.155:3306;
server 10.124.207.154:3306 backup;
}
server {
listen 3306;#公网机器监听端口
proxy_connect_timeout 10s;
proxy_timeout 800s;
proxy_pass mysql;
}
}

mysql 为 docker-compose 文件下的名称

创建 config/nginx/log/access.log or error.log

MySQL 配置

编写 config/mysql/my.conf

# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0 log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid #server-id=1
log_bin = mysql-bin # 开启二进制log文件
binlog_format = mixed
#relay-log = relay-bin
#relay-log-index = slave-relay-bin.index
#auto-increment-offset = 1 # 从 1 开始
#auto-increment-increment = 2 # 每次增长 2 character-set-server=utf8 [client]
default-character-set=utf8 [mysql]
default-character-set=utf8 [mysqld]
skip-name-resolve

编写初始化 config/mysql/init/init.sql

CREATE USER 'test'@'%';

GRANT ALL PRIVILEGES ON *.* To 'test'@'%' IDENTIFIED BY 'testPass1!';

FLUSH PRIVILEGES;

CREATE DATABASE IF NOT EXISTS test default charset utf8 COLLATE utf8_general_ci;

编写 docker-compose 文件:

version: '3'

services:
mysql:
image: ctg/mysql:5.7.29
container_name: "mysql"
environment:
MYSQL_ROOT_PASSWORD: "MyNewPass1!"
restart: always
ports:
- "3306:3306"
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "./db_storage:/var/lib/mysql"
- "./config/mysql/my.cnf:/etc/my.cnf"
- "./config/mysql/init:/docker-entrypoint-initdb.d/"
networks:
- app_net proxy_server:
image: ctg/nginx:latest
ports:
- "443:443"
- "3307:3307"
- "444:444"
- "666:666"
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "./project:/src"
- "./config/nginx/conf.d:/etc/nginx/conf.d"
- "./config/nginx/default.d:/etc/nginx/default.d"
- "./config/nginx/log:/var/log/nginx"
- "./config/nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./frontend:/var/frontend"
container_name: "proxy_server"
depends_on:
- web
networks:
- app_net
web:
image: ctg/web:latest
container_name: "ctg_backend"
command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --noinput && gunicorn -c gunicorn_config.py ctg.wsgi" ports:
- "8000:8000"
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "./project:/src"
- "/proc:/hostip/:ro"
restart: always
privileged: true
networks:
- app_net topo:
image: ctg/topo:latest
container_name: "ctg_topo"
command: bash -c "python /ctg_topo/manage.py runserver 0.0.0.0:7777" ports:
- "7777:7777"
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "./topo_project/topo_server:/ctg_topo"
restart: always
networks:
- app_net networks:
app_net:
driver: bridge
ipam:
config:
- subnet: 172.26.0.1/16

由于 nginx 和 django 是分开部署的,记得把 django 层收集的静态文件也给 nginx 拷贝一份,否则会导致 admin 管理界面样式丢失。我这里的 frontend 是又另外的 portal 界面,忽略即可

想着修改 django 项目的 settings.py 文件,添加如下内容:

ALLOW_HOSTS = ['web']
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

运行

构建镜像:

docker-compose build

如果上述构建成功的话,就可以运行容器了:

docker-compose up -d

如果 docker-compose 的容器是以守护进程运行的话,可以使用下面的命令查看容器的日志:

docker-compose logs -f web

配置开机自启动

# 配置 docker 自启动
systemctl enable docker

配置docker-compose自启动可参考 自启动. 编写 config/auto_start_script.sh 文件。

将 python 转为 pyc 文件

在 django manage.py 同级别执行

# 生成 pyc 文件:
python -m compileall -b . # 删除 py 文件:
find . -name "*.py" |xargs rm -rf # 删除 pycache 目录:
find . -name "pycache" |xargs rm -rf # 最后将 docker-compose.yml 文件中涉及到的 py 文件 换成 pyc.
需要注意的是 gunicorn_config.py 要备份一份,该文件不要转成 pyc.

如果想要实现通过 Jenkins 自动编译加部署,可以参考Jenkins 实现 CI/CD.

参考

how-to-create-a-self-signed-ssl-certificate-for-nginx-on-centos-7

docker ce install

Nginx 、MySQL、Django 在 Docker-compose 中的部署的更多相关文章

  1. Docker Compose 项目打包部署

    Docker Compose 前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build.docker run 等命令操作容器.然而微服务架构的应用系统一 ...

  2. Docker Compose编排工具部署lnmp实践及理论(详细)

    目录 一.理论概述 编排 部署 Compose原理 二.使用docker compose 部署lnmp 三.测试 四.总结 一.理论概述 Docker Compose是一个定义及运行多个Docker容 ...

  3. Django在生产环境中的部署

    基本思路 1.方案:Nginx+uwsgi 这样大体的流程是:nginx作为服务器最前端,负责接收client的所有请求,统一管理.静态请求由Nginx自己处理.非静态请求通过uwsgi传递给Djan ...

  4. MySQL(6)--复制,docker容器中

    MySQL5.7.11实现replication 启动两个安装好mysql的空的docker image ----------------- shell1  master $docker run -i ...

  5. Nginx+uWSGI+Django+Python在Linux上的部署

    搞了一整天,终于以发现自己访问网络的端口是错误的结束了. 首先要安装Nginx,uWSGI,Django,Python,这些都可以再网上查到. 安装好后可以用 whereis 命令查看是否安装好了各种 ...

  6. 基于Docker Compose构建的MySQL MHA集群

    Docker MySQL MHA 基于Docker 1.13.1之上构建的MySQL MHA Docker Compose Project 可快速启动GTID模式下的MasterHA集群, 主用于My ...

  7. Docker + node(koa) + nginx + mysql 线上环境部署

    在上一篇 Docker + node(koa) + nginx + mysql 开发环境搭建,我们进行了本地开发环境搭建 现在我们就来开始线上环境部署 如果本地环境搭建没有什么问题,那么线上部署的配置 ...

  8. Docker学习笔记之编写 Docker Compose 项目

    0x00 概述 通过阅读之前的小节,相信大家对 Docker 在开发中的应用已经有了一定的了解.作为一款实用的软件,我们必须回归到实践中来,这样才能更好地理解 Docker 的实用逻辑和背后的原理.在 ...

  9. Docker学习笔记之常用的 Docker Compose 配置项

    0x00 概述 与 Dockerfile 一样,编写 Docker Compose 的配置文件是掌握和使用好 Docker Compose 的前提.编写 Docker Compose 配置文件,其本质 ...

  10. Docker学习笔记之使用 Docker Compose 管理容器

    0x00 概述 通过之前的介绍,我们已经基本掌握了构建.运行容器的方法,但这还远远不够,由于 Docker 采用轻量级容器的设计,每个容器一般只运行一个软件,而目前绝大多数应用系统都绝不是一个软件所能 ...

随机推荐

  1. view-controller

    有的时候我们只想根据一个请求地址跳转到一个页面中,中间并没有任何的处理流程,这个时候创建一个 Controller 类再编写方法来跳转就显得很繁琐.这个时候我们就可以使用 view-controlle ...

  2. java学习(第二篇)语法学习

    1.java标识符 类名.变量名以及方法名都被称为标识符. 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($).或者下划线(_)开始 首字符之 ...

  3. 【Inno Setup】Pascal 脚本 ---- 事件函数

    转载 事件函数 Inno Setup支持以下函数和过程. 1. [安装初始化]该函数在安装程序初始化时调用,返回False 将中断安装,True则继续安装,测试代码如下: function Initi ...

  4. HDU 5451 Best Solver

    没有意识到循环节最大是M^2,用域Z_M下二阶可逆矩阵群的最大循环节(M^2-1)*(M^2-M)来做,考虑大数乘法,矩阵乘法,做到吐血.将代码贴在下方留作纪念. #include<bits/s ...

  5. [转] Exchange 2013 安装部署详解

    ·Exchange 2013 部署:系统要求 823 / 3 部署 系统要求 Exchange 2013 zhou_ping 2013-02-17 ·Exchange 2013 部署:先决条件 752 ...

  6. 无法打开到SQL Server的连接 (Microsoft SQL Server, 错误:53) .

    标题: 连接到服务器 ------------------------------ 无法连接到 MSSQLSERVER. ------------------------------ 其他信息: 在与 ...

  7. Mockjs+Ajax实践

    需要完成的工作:利用mock js随机生成数据,通过ajax请求,获取这些数据并展示在网页中. 一 mock js随机生成数据 官方文档中,Mock.mock( ),可以说是mock的精髓所在. Mo ...

  8. 02-线性结构3 Reversing Linked List

    02-线性结构3 Reversing Linked List   (25分) 时间限制:400ms 内存限制:64MB 代码长度限制:16kB 判题程序:系统默认 作者:陈越 单位:浙江大学 http ...

  9. JS编程建议——11:慎重使用伪数组

    建议11:慎重使用伪数组JavaScript没有真正的数组,因此typeof运算符不能辨别数组和对象.伪数组在JavaScript中有很高的易用性,程序员不用给它设置维度,而且永远不用担心产生越界错误 ...

  10. PHP版DES算法加密数据(3DES)另附openssl_encrypt版本

    PHP版DES算法加密数据(3DES) 可与java的DES(DESede/CBC/PKCS5Padding)加密方式兼容 <?php /** * Created by PhpStorm. * ...