失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Docker部署Angular+Nginx+uwsgi+Django项目

Docker部署Angular+Nginx+uwsgi+Django项目

时间:2018-08-15 10:02:10

相关推荐

Docker部署Angular+Nginx+uwsgi+Django项目

Docker部署Angular+Nginx+uwsgi+Django项目

0、前言

在开发部署时,容易遇到服务器环境不一致,多台服务重复部署操作过于繁杂的情况。这时可以采用Docker来提供一套统一的环境和帮助我们快速部署项目。

本篇文章先介绍下Docker是什么,怎么安装使用,然后用一个比较常见的Angular+Nginx+uwsgi+Django框架模式的项目的说明怎么用Docker将各个服务结构搭建连接使用,说了下怎么利用Docker来提供环境来生成Angular编译打包的文件。

第一章简单的介绍Docker并说明其安装方式(已了解过Docker可以忽略)。

第二章说明各个结构服务项目部署以及其配置文件。

第三章怎么使用Docker Compose对Docker进行整合运用发布。

1、Docker介绍

Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。

在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

Docker的应用场景

Web 应用的自动化打包和发布。自动化测试和持续集成、发布。在服务型环境中部署和调整数据库或其他的后台应用。从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。

1.1、Docker 安装

命令行运行docker命令的时候,需要本机有 Docker 服务。

安装方式最好根据官方文档说明进行安装。

这里说明下Debian系统的安装流程

sudo apt-get updatesudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg2 \software-properties-commoncurl -fsSL /linux/debian/gpg | sudo apt-key add -sudo apt-key fingerprint 0EBFCD88sudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io

如果服务没有启动,可以用以下指令启动

sudo service docker start# service 命令的用法sudo systemctl start docker # systemctl 命令的用法

验证是否安装成功

sudo docker run hello-world

查看到Hello from Docker 即表示安装成功

Docker 需要用户具有 sudo 权限,为了避免每次命令都输入sudo,可以把用户加入 Docker 用户组。

注:输入指令后需要关闭终端重新连接生效。

sudo usermod -aG docker $USER

1.2、Docker基本概念

Docker主要有三个基本概念,仓库(Repository)、镜像(Image)、容器(Container)。

仓库:Docker仓库的概念和Git类似,仓库注册服务器可以理解为GitHub的托管服务。其区别在于Git仓库是提供代码文件的存储和下载,Docker仓库是提供镜像文件存储和下载,用户创建了镜像后可以push到仓库中,下次需要使用可以从仓库pull下来。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式,仓库的概念有时会和仓库注册服务器(Registry)混为一谈,但实际是仓库注册服务器上存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同标签(tag)。

Docker官方维护了一个公共仓库 Docker Hub ,基本的需求都可以通过Docker Hub 下载镜像实现。

用户无需登录即可通过docker search命令来查找官方仓库中的镜像,并利用docker pull命令来将它下载到本地。

镜像:Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

容器:Docker利用容器运行应用,是从镜像创建的实例。每个容器都是相互隔离。

可以通过–help 查看docker 指令,参数,作用。

2、项目部署

项目结构

Safety├── SafetyTest # 从git 仓库├── SafetyServer # 从git 仓库clone下来的Django 项目代码├── docker-compose.yml # docker-compose文件├── docker-pile # 前端Angular环境的Dockerfile文件├── docker-pile # 后端Django环境的Dockerfile文件├── docker-plile # 配置nginx的Dockerfile文件├── www# 存放Angular编译后的文件├── mysql # 存放mysql数据文件,MySQL数据持久化├── nginx.conf # nginx 通用配置文件├── conf.d # nginx 配置路由文件夹├── ├── safetyfront.conf# 前端配置文件├── ├── safetyserver.conf # 后端配置文件

完整的服务通过Mysql服务提供数据存储,Web应用服务提供功能使用,Nginx服务做运维HTTP服务器和反向代理服务器。

2.1、 MySql服务容器服务

docker run -p 3307:3360 -d --volume "$PWD/mysql/":/var/lib/mysql --env MYSQL_ROOT_PASSWORD=123456 --env MYSQL_DATABASE=safety --name=safety_mysql mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

运行该命令会通过mysql:5.7镜像(本地无该镜像则会自动从官方仓库拉取该镜像)生成mysql服务容器

-p 端口映射,格式为:主机(宿主)端口:容器端口;d: 后台运行容器,并返回容器ID;–volume 挂载,将本地文件夹挂载到容器中,格式为: 主机文件夹路径:容器文件夹路径,挂载了mysql数据目录,可实现数据持久化–env 设置环境变量,这里设置了mysql root用户密码和生成名为safety 的mysql数据库,(mysql镜像设置了生成容器后的自动运行脚本,会安装mysql数据库并根据设置的环境变量做一些自动化处理);–name 为容器指定一个名称;

docker ps

查看运行中的容器,若NAMES 列存在 为容器设置的别名则表示容器生成成功。

docker exec -it safety_mysql /bin/bash #进入容器mysql -u root -p #使用数据库,并输入密码show databases #查看数据库

若存在环境变量设置的数据库名称则表示数据库生成成功。

2.2、Web应用容器服务

由于不同web应用所需依赖环境不一致,一般情况需要编写Dockerfile文件来生成镜像,再由镜像文件生成容器。镜像上传了仓库则可直接下载仓库镜像生成容器。

在构建 Docker 容器时,应该尽量想办法获得体积更小的镜像,因为传输和部署体积较小的镜像速度更快,而且为了保证项目代码的保密性,不建议将项目代码放入镜像文件中,所以在生成环境时只生成项目所需的运行环境到镜像中,运行时通过配置volume 将项目代码文件挂载在容器中即可。

2.2.1、编写镜像文件,uwsgi配置文件和项目启动脚本

docker-pile

FROM python:2.7 LABEL authors=""WORKDIR /usr/src/app/COPY SafetyTestServer/requirements.txt requirements.txtRUN pip install -r requirements.txtENTRYPOINT ["sh","restart.sh"]

FROM python:2.7: 继承python:2.7镜像生成LABEL: 标签,一般写说明Dockerfile文件编写者的信息WORKDIR: 指定接下来的工作路径,路径不存在会创建路径COPY : 将本地文件拷贝到镜像文件目录中RUN : 运行指令,用与安装指令ENTRYPOINT: 配置容器启动时运行的命令

运行 docker build 指令生成镜像

docker build -f docker-pile -t safetyserver-env .

-f: 指定DockerFile文件-t: 指定镜像名及版本号,格式 镜像名:版本号命令行尾部的 . 表示当前目录

Safety/SafetyTestServer目录为应用代码目录,目录下存在uwsgi.ini文件及restart.sh 文件,uwsgi.ini文件为通过uwsgi启动Django项目的配置文件,restart.sh则是处理启动的脚本。

uwsgi.ini

[uwsgi]chdir = /usr/src/appmodule = SafetyTest.wsgi:applicationsocket = 0.0.0.0:82master = truepidfile = /usr/src/app/safetytest.pidenv DJANGO_SETTINGS_MODULE = SafetyTest.settingsprocesses = 5harakiri = 20max-requests = 5000vacuum = truebuffer-size = 32768daemonize = /usr/src/app/uwsgi.log

restart.sh

uwsgi --stop /tmp/safetytest.pidsleep 3uwsgi --ini uwsgi.inisleep infinity #为保持容器不自动关闭

2.2.2、启动容器

docker run -p 82:82 -d --rm --volume "$PWD/SafetyTestServer/":/usr/src/app/ --name=safety_server --link=safety_mysql:safety_mysql safetyserver-env

2.3、Nginx容器服务

2.3.1、Angular 编译打包

熟悉Angular 项目的同学应该知道Angular需要经过编译生成dist文件,前端实际显示的为dist文件内容。Angular是通过node进行编译的,而且需要安装对应的模块依赖。

为了保障环境的稳定,所以我将编译Angular项目的环境也Docker化,确保各个服务器的依赖的统一。

编写镜像文件docker-pile

docker-pile

FROM node:10LABEL authors="lq"WORKDIR /usr/src/appCOPY SafetyTest/package.json package.jsonRUN npm installRUN npm install -g @angular/cli

同样镜像文件中我并没有放入项目代码,那么如何实现将项目代码通过环境进行编译生成dist文件并获取呢?这里编写了docker-front.sh脚本处理。

docker-front.sh#!/bin/bash# author:a="true"#如果运行脚本时添加true, 如:sh docker-front.sh true,则会更新镜像if [ $1 = $a ] thenecho 'new environment'docker build -f pile -t safetytest-env:latest .#生成新的镜像docker push safetytest-env:latestecho 'new environment success'elseecho 'old environment'fiecho 'pull environment'docker pull safetytest-env#向仓库拉取镜像echo 'pull environment success'docker run -itd --name safety safetytest-env /bin/bash#运行镜像生成名为safety 的容器docker cp ./SafetyTest/ safety:/usr/src/app/#拷贝本地文件到safety容器中docker exec safety ng build --prod --aot# 对safety容器执行ng build --prod --aot 指令编译打包文件docker cp safety:/usr/src/app/dist ./www/dist#拷贝safety容器中编译生成好的dist文件到本地www文件夹中docker container stop safety#停止safety容器docker container rm safety#移除safety容器 (容器停止后可以通过start 重新恢复容器运行,如果不需要该容器了则stop后需要移除,释放系统资源)

运行完后查看www文件夹中是否存在dist文件,存在表示运行成功,Angular编译打包完成

2.3.2、Nginx配置文件

Nginx提供服务需要通过配置相应项目的Nginx服务启动。

Safety 文件目录下有nginx.conf通用配置文件,conf.d 项目文件夹,nginx.conf通用配置一般是为了为Nginx设置一些通用参数来提供性能,可以替换可以不替换。conf.d目录下则是具体项目的配置文件。

conf.d

├── safetyfront.conf # 前端配置文件

└── safetytest.conf # 后端配置文件

safetyfront.conf

server {listen 80;server_name 服务器地址;charset utf-8;client_max_body_size 75M;access_log /var/www/nginxAccess-angular.log;error_log /var/www/nginxError-angular.log;location / {root /var/www/dist;index index.html;try_files $uri $uri/ /index.html;}}

safetytest.conf

upstream safetytest{server 服务器地址:82;}server {listen 81;server_name 服务器地址;charset utf-8;client_max_body_size 1G;keepalive_timeout 600;access_log /var/www/nginxAccess.log;error_log /var/www/nginxError.log;location / {uwsgi_pass safetytest;uwsgi_read_timeout 600;include /etc/nginx/uwsgi_params;if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '$http_origin';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Authorization';add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Content-Length' 0;return 204;}if ($request_method ~ (POST|PUTPATCH)) {add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';}if ($request_method = 'GET') {add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';}}location /resource {alias /var/www/data/;}location /static {alias /var/www/static/;}}

2.3.3、Nginx镜像文件及容器

编写镜像文件

docker-pile

FROM nginx:1.10.2ADD nginx.conf/etc/nginx/nginx.confADD conf.d/* /etc/nginx/conf.d/

生成nginx镜像

docker build -f docker-pile -t safety-nginx .

生成nginx容器

docker run -d -p 81:81 -p 80:80 --rm --volume "$PWD/www/":/var/www/ --name=safety_nginx safety-nginx

这样完整的一套Docker部署就完成了,可以通过浏览器进行访问。

小提示:

Django需要初始化数据库, 可以进入容器执行对应初始化命令,或者通过编写脚本让容器运行

docker exec -it safety_server /bin/bashpython manage.py makemigrations...#其他命令,通过exit 推出容器

3、Docker Compose

Docker Compos 是docker进行整合发布应用的利器,用来定义和运行复杂应用的Docker容器应用,可以通过编写配置文件实现多个Docker容器服务的启动。

3.1、安装

不同系统可以根据官方安装指南进行安装

Debian系统安装方式

sudo curl -L "/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-composesudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

验证是否安装成功

docker-compose --version

显示了docker-compose的版本好即表示安装成功

3.2、 配置文件

Docker-compose 运行时若没有指定文件则会在运行指令目录下找名为docker-compose.yml文件作为配置文件进行服务启动。

docker-compose.yml

version: '2'services:mysql:image: mysql:5.7volumes:- ./mysql/:/var/lib/mysqlports:- 3307:3306networks:- mysqlendenvironment:- MYSQL_ROOT_PASSWORD=123456- MYSQL_DATABASE=safetyweb:image:safetyserver-envports:- 82:82networks:- mysqlendvolumes:- ./SafetyTestServer/:/usr/src/app/links:- mysqlweb-nginx:image: safety-nginxports:- 81:81- 83:80volumes:- ./www/:/var/www/links:- webnetworks:mysqlend:

verison: 记录版本信息services: 需要启动的容器服务,其子节点为用户自定义的容器服务名称image: 指定启动容器的镜像volumes: 文件挂载ports: 容器和主机映射的端口environment: 启动容器的环境变量links: 链接到另一个服务容器networks: 加入指定网络服务

3.3、 运行

docker-compose up #启动配置的docker容器服务docker-compose stop #关闭配置的容器服务,容器依然存在,容器内内容不会丢失docker-compose rm #将配置的容器服务移除

如果觉得《Docker部署Angular+Nginx+uwsgi+Django项目》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。