docker+django+vue实例开发之一:搭建开发环境(二
2)基于docker搭建开发环境
在docker出现之前,每次搭建开发环境都需要在linux bash上操作,安装一堆依赖、库等等,这样效率很低,而且不同环境还会出现各种问题,docker出现之后,只需要找一个基本的liunx镜像,将开发环境搭建操作以脚本方式附加在基础镜像之上,形成新的镜像,通过这个镜像实例化的容器就可以到处部署和使用。本实例前后端配置都是放在docker镜像脚本中自动构建的,下文会将镜像脚本贴出来并附加注释。
(1)进入centos7环境,安装docker并设置开机自启动
yum -y install docker-io
systemctl enable docker
(2)安装docker
composer,dc是docker的服务编排工具,通过一个yml文件来管理多个docker容器,可以搭建聚集多个docker的复杂应用。
yum update curl
curl -L https://github.com/docker/compose/releases/download/1.24.0-rc1/docker-compose -uname -s -m -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose -version
(3)将git用户赋予sudo权限,并纳入docker使用组
visudo ##root用户下操作
在## Allowroot to run any commands anywhere
root ALL=(ALL) ALL
下面添加git ALL=(ALL) ALL
chown -R git /etc
su git
sudo groupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp - docker
(4)在本地win 7下的TNDBXXXT.git版本库所在文件夹下建立如下所示项目目录,从目录结构中可看出,本项目一共需创建2个容器,一个web容器和一个mysql数据库容器,前者从centos镜像中构建,后者直接拉取mysql容器使用。
document 开发文档目录
code 开发代码目录
—webapi web服务api(如果有多个后端,可以命名区分)
—pcfront pc浏览器前端(如果有多个前端,例如admin等等,可以命名区分)
docker docker文件根目录
—backend 后端目录,作为后端代码共享卷
——backend.conf 后端api的nginx配置
——requirements.txt python开发所需依赖包
—frontend 前端目录,作为前端代码共享卷
——frontend.conf 前端的nginx配置
—nginx ningx配置目录
——nginx.conf nginx配置文件,将替换docker容器中nignx.conf
—db 数据库目录,作为数据库配置、日志和数据的共享卷
——mysqlinit mysql初始化脚本共享卷
——mysqldata mysql数据共享卷
——mysqllog mysql日志共享卷
——mysqlconf mysql配置文件共享卷
—Dockerfile qicrsweb镜像的手动构建脚本文件,主要工作所在
—start_scirpt qicrsweb镜像启动入口脚本文件,linux批处理文件
—.env 多容器间共享的环境变量文件
—wait_for_it.sh 服务启动顺序控制脚本文件,linux批处理文件
—docker-compose.yml docker服务编配脚本文件
(5)编写Dockerfile文件如下,可以看出,docker镜像脚本基本就是linux
bash命令的转换,当然你也可以从其它已经部署好python等环境的docker镜像开始干,就需要去掉已有的内容。
####基础镜像
FROM centos:7
####作者
MAINTAINER clz
####设置时区
ENV TZ "Asia/Shanghai"
####安装nginx
RUN yum install epel-release -y
RUN yum install nginx -y
RUN systemctl enable nginx
###安装python3和pip3
RUN yum groupinstall 'Development Tools' -y
RUN yum install gcc -y
RUN yum install zlib-devel -y
RUN yum install bzip2-devel -y
RUN yum install openssl-devel -y
RUN yum install ncurses-devel -y
RUN yum install wget -y
RUN wget http://mirrors.sohu.com/python/3.5.2/Python-3.5.2.tar.xz
RUN tar xvf Python-3.5.2.tar.xz
RUN ./Python-3.5.2/configure --prefix=/usr/local/python3--enable-shared CFLAGS=-fPIC
RUN export PYTHONHOME=/usr/local/python3
RUN export PYTHONPATH=.:$PYTHONHOME:$PYTHONHOME/site-packages
RUN export PATH=$PATH:$PYTHONHOME:$PYTHONPATH
RUN make && make install
RUN echo "/usr/local/python3/lib" >/etc/ld.so.conf.d/python3.conf
RUN ldconfig
RUN ln -s /usr/local/python3/bin/python3.5 /usr/bin/python3
RUN ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
RUN pip3 install --upgrade pip
####安装uwsgi
RUN mkdir /uwsgi
WORKDIR /uwsgi
RUN wget http://projects.unbit.it/downloads/uwsgi-2.0.15.tar.gz
RUN tar zxvf uwsgi-2.0.15.tar.gz
WORKDIR uwsgi-2.0.15
RUN echo "plugin_dir = /uwsgi" >> buildconf/core.ini
RUN echo "bin_name = /usr/bin/uwsgi" >>buildconf/core.ini
RUN python3 uwsgiconfig.py --build core
RUN python3 uwsgiconfig.py --plugin plugins/python core python3
WORKDIR /root
####安装mysql客户端
RUN yum install mysql-devel -y
####安装python三方库
ADD backend/requirements.txt /tmp/
RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r/tmp/requirements.txt
####创建同一权限用户运行nginx、uwsgi,并将/var/www文件夹权限赋予它
RUN adduser git
RUN chown -R git /var
####增加配置文件
ADD frontend/frontend.conf /etc/nginx/conf.d/
ADD backend/backend.conf /etc/nginx/conf.d/
RUN rm /etc/nginx/nginx.conf
ADD nginx/nginx.conf /etc/nginx/
####执行服务启动脚本
ADD start_script ./
ADD wait_for_it.sh ./
RUN chmod u+x start_script
ENTRYPOINT ["./start_script"]
(6)编写requirements.txt,该文件将包含后端服务运行所需所有python依赖库需求,最简单的方式就是在本地win7的cmd中输入pip list,查看本地机器运行后端api需要哪些库,然后拷贝到requirements.txt中,本实例的requirements.txt内容如下:
django==1.11.4
djangorestframework==3.8.2
django-cors-headers
drfdocs
matplotlib
mongoengine
mysql-connector-python
mysqlclient
Pillow
redis
requests
reportlab
(7)编写nginx.conf系列文件,这些文件是以nginx作为服务器运行前后端应用的配置文件,内容分别如下:
## nginx.conf文件
user git;
worker_processes auto;
worker_rlimit_nofile 100000;
pid /run/nginx.pid;
events {
worker_connections 5000;
multi_accept on;
use epoll;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status$body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server_tokens off;
access_log /var/log/nginx/access.log;
error_log/var/log/nginx/error.log; ##错误日志文件,有502等错误时查看
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_header_timeout 600;
client_body_timeout 600;
client_max_body_size1024m;
reset_timedout_connectionon;
client_header_buffer_size4k;
open_file_cache max=100000inactive=20s;
open_file_cache_valid600s;
open_file_cache_min_uses1;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_proxied any;
gzip_min_length 1000;
gzip_comp_level 4;
gzip_types text/plaintext/css application/json application/x-javascript text/xml application/xmlapplication/xml+rss text/javascript;
include/etc/nginx/conf.d/*.conf; ##将包含所有前后端config文件
proxy_read_timeout 1800;
fastcgi_buffers 8 256k;
send_timeout 1800;
}
## backend.conf后端配置
server {
listen 8000;
server_name clz.api.net;
charset utf-8;
client_max_body_size 100M;
location / {
uwsgi_passunix:///var/www/webapi/webapi.sock; ##sock文件方式,##在部署后端代码##时会有相应说明
include/etc/nginx/uwsgi_params;
}
}
## frontend.conf 前端配置
server {
listen 80 deferred;
server_name jstv.net;
root/var/www/pcfront/dist; ##前端build文件位置
index index.html index.htm;
location / {
index index.htmlindex.php;
autoindex on;
}
# nginx redirect
location /api_web { ##用于跨域重定向后端api
rewrite ^.+api_web/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://localhost:8000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
#log
access_log/var/log/nginx/jstv_access.log;
error_log/var/log/nginx/jstv_error.log;
}
(8)编写数据库初始化脚本init.sql,该文件放置于mysqlinit文件夹下,加载mysql容器时会自动对数据库进行初始化,需要注意的是,开发时可能仅需建立一个用户和一个数据库,到部署时,一些开发过程中创建的表、数据结构、存储过程等,就需要导出到init.sql文件。本项目init.sql文件初始如下:
create database jsty;
grant all PRIVILEGES on jsty.* to jsty@'%' identified by 'jsty123';
flush privileges;
use jsty;
(9)编写start_script文件。start_script文件是容器运行的入口文件,用于初始化环境变量、设置等操作。由于本项目的web容器依赖于mysql容器,故先启动mysql容器,在start_script中使用了wait_for_it.sh这样一个批处理指令集检测mysql容器是否已启动。start_script内容如下:
#!/bin/bash
####赋予wait_for_it.sh可执行权限
chmod u+x wait_for_it.sh
####判定依赖容器mysql是否已运行
./wait_for_it.sh $DB_MYSQL_HOST:$DB_MYSQL_PORT & wait
####启动uwsgi
uwsgi --plugin python3 --ini /var/www/webapi/webapi_uwsgi.ini--pidfile /var/run/webapi_uwsgi.pid
####启动nginx
nginx -g 'daemon off;'
(10)设置环境变量.env。两个容器之间可以共享环境变量,而且初始化容器时也需要从环境变量中读取mysql容器参数,如数据库名、用户名、密码等。注意windows上使用txt建立.env文件会要求输入文件名称,此时使用“另存为”选项即可。
DEBUG=False ##后端是否处于调试模式
MYSQL_ROOT_PASSWORD=jsty123
WEB_HOST=web ##自动映射web容器ip
DB_MYSQL_HOST=mysql ##自动映射mysql容器ip
DB_MYSQL_PORT=3306
DB_MYSQL_DB=jsty
DB_MYSQL_USER=jsty
DB_MYSQL_USER_PWD=jsty123
(11)编写服务编排文件docker-compose.yml。yml文件中通过link和depends_on两个关键词描述了容器之间的依赖,并将容器运行的参数全部提供,如下:
version: '3'
services:
web: ##web容器
restart: always
image:"jsty-web" ##镜像名称,意味着我们先要使用dockerfile build镜像
container_name: "jstyweb" ##容器名称
privileged: true ##权限,必须打开,否则无法访问挂载卷
ports: ##端口
- "80:80"
- "8000:8000"
volumes: ##挂载卷
-/home/git/docker/frontend:/var/www/pcfront:ro
-/home/git/docker/backend/webapi:/var/www/webapi
links: ##建立静态连接
- mysql
depends_on: ##容器依赖
- mysql
env_file:/home/git/docker/.env ##环境变量
mysql:
restart: always
image: "docker.io/mysql:5.6"
container_name:"mysql"
privileged: true
ports:
- "3306:3306"
volumes:
-/home/git/docker/db/mysqldata:/mysql_data
-/home/git/docker/db/mysqllog:/logs
-/home/git/docker/db/mysqlconf:/etc/mysql/conf.d
-/home/git/docker/db/mysqlinit:/docker-entrypoint-initdb.d
env_file: /home/git/docker/.env
(12)构建web镜像。将编写好的所有目录push到服务器上,然后在服务器远程shell上进行操作,切换到git用户,在其根目录下克隆一份TNDBXXXT库文件,然后将其中的docker文件夹拷贝到git用户根目录下,进入该目录构建镜像。
su git
cd
git clone git@/home/git/repositories/TNDBXXXT.git
cp -rf TNDBXXXT/docker docker
cd docker
docker build -t jsty-web . ## 注意后面有个“.”,构建过程遇到错误自行改正
docker images ##可以查看构建完成的镜像
(13)运行容器。在第12步中创建的docker目录下使命令docker-compose
up即可运行容器,该命令在镜像更新时会自动拉取镜像重新创建容器,没有更新时则启动容器(重启容器需要用docker-compose restart)。容器启动后可用docker ps查看正在运行的容器,由于现在还未放入任何前后端代码,现在也不会看到任何东西,因此,我们还需要编写一个作为开发基础的前后端工程模板。
注意事项:
解决使用docker时报错“net/http: TLS handshake timeout”
git用户下执行
curl -sSL
https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
然后重启docker服务
Sudo service docker restart