概述

本文主要记录了在 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. SpringBoot项目集成Redis

    一.在pom文件中添加依赖 <!-- 集成redis --> <dependency> <groupId>org.springframework.boot</ ...

  2. Async,Await 深入源码解析

    1.同步与异步 假设存在 IO事件A:请求网络资源 (完成耗时5s) IO事件B:查询数据库 (完成耗时5s) 情况一:线程1工人在发起A请求后,一直阻塞等待,在A响应返回结果后再接着处理事件B,那总 ...

  3. Add text to 'Ready Page' in Inno Setup

    https://stackoverflow.com/questions/1218411/add-text-to-ready-page-in-inno-setup

  4. Vue3.0新版API之composition-api入坑指南

    关于VUE3.0 由于vue3.0语法跟vue2.x的语法几乎是完全兼容的,本文主要介绍了如何使用composition-api,主要分以下几个方面来讲 使用vite体验vue3.0 composit ...

  5. java中Locks的使用

    文章目录 Lock和Synchronized Block的区别 Lock interface ReentrantLock ReentrantReadWriteLock StampedLock Cond ...

  6. awk命令及随机数的产生

    3.sed 操作,将文件第9行至第15行的数据复制到第十六行 sed -i  '9,15H;16G' 文件 4.用awk获取文件中的三行的倒数第二列字段 awk -F":" 'NR ...

  7. Android 5.0系统默认颜色

    伴随着 Android5.0 的发布也更新了support-v7-appcompat 到 V21,其中增加了 ToolBar.recyclerview.cardview 等控件. Android5.0 ...

  8. Flex 布局教程:语法篇(转自阮一峰的网络日志)

    作者:阮一峰(转自阮一峰的网络日志,如有侵权,立即删除) 网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 ...

  9. 桌面上的Flutter:Electron又多了个对手

    从本质上看,Flutter是一个独立的二进制可执行文件.它不仅改变了移动设备的玩法,在桌面设备上也同样不可小觑.一次编写,可在Android.iOS.Windows.Mac和Linux上进行原生部署, ...

  10. 数论--HDU 1495 非常可乐

    Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和se ...