Dockerfile搭建环境并打包应用

在上一章Docker构建nginx+uwsgi+flask镜像(一)的学习中,我们学会用命令行一句一句在alpine环境中搭建nginx+uwsgi+flask服务,但这体现不了Docker为我们带来的便利,而本章,我们将通过Dockerfile来制作基础镜像和打包应用,因此会有两个Dockerfile文件。

我们先来写第一个Dockerfile文件,这个文件负责搭建运行环境,运行环境需要包括:nginx、uwsgi、Python3:

# 配置基础镜像
FROM alpine:3.8 # 添加标签说明
LABEL author="moshangguang" email="XXX@qq.com" purpose="nginx+uwsgi+Python3基础镜像" # 配置清华镜像地址
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.8/main/" > /etc/apk/repositories # 更新升级软件
RUN apk add --update --upgrade # 安装软件
RUN apk add --no-cache nginx python3 uwsgi uwsgi-python3 # 升级pip,这一步同时会在/usr/bin/目录下生成pip可执行文件
RUN pip3 install --no-cache-dir --upgrade pip # 建立软链接
RUN ln -s /usr/bin/python3 /usr/bin/python

     

上面的安装软件相比之前少了个vim,因为之前我们是在容器内部编辑配置文件,所以需要这个命令,但现在我们的配置文件都是预先在容器之外编辑好在通过docker拷贝到容器内部,所以也就无需安装vim。另外建立软连接时,我们只建立了从python到python3的软连接,没有建立pip到pip3的软链接,因为/usr/bin/pip在安装软件时已经生成。

执行docker build命令,生成镜像,执行docker images命令可以看到生成nginx_uwsgi_py3镜像,标签为alpine3.8:

[root@ docker]# docker build -t nginx_uwsgi_py3:alpine3.8 .
Sending build context to Docker daemon 4.096 kB
……
Successfully built 63be35fe36ca
[root@ docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx_uwsgi_py3 alpine3.8 63be35fe36ca 5 minutes ago 60 MB

  

于是,我们完成了第一个Dockerfile文件,这个Dockerfile文件可以为我们搭建我们所需要的运行环境镜像。

我们可以把构建好的基础镜像推送到我们的Docker hub仓库,先用docker login登录之后

[root@ docker]# docker login -u moshangguang -p 123456
Login Succeeded

  

tips:上面登录密码是假的哈。

然后为我们的镜像打上tag,之后推送镜像。

[root@ docker]# docker tag 687445ba4c7f moshangguang/nginx_uwsgi_py3:alpine3.8
[root@ docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
moshangguang/nginx_uwsgi_py3 alpine3.8 63be35fe36ca 22 minutes ago 60 MB
nginx_uwsgi_py3 alpine3.8 63be35fe36ca 22 minutes ago 60 MB
[root@iZj6c0zloujsauztjjhyhgZ docker]# docker push moshangguang/nginx_uwsgi_py3:alpine3.8
The push refers to a repository [docker.io/moshangguang/nginx_uwsgi_py3]
……
alpine3.8: digest: sha256:412ec97c1c51dffeee6b924494bc size: 1154

  

有了基础镜像,我们就可以开始编写我们的应用了,这里先给出我们应用的目录结构(web_app在github上的地址):

[root@ docker]# tree web_app
web_app
├── app
│   ├── app.py
│   ├── requirements.txt
│   └── uwsgi.ini
├── Dockerfile
└── nginx.conf 1 directory, 5 files

  

最外层的web_app目录包含一个app目录,和两个文件,分别是Dockerfile、nginx.conf,注意,web_app下的Dockerfile文件和之前的Dockerfile文件不同,这里的Dockerfile文件是用来打包应用的。nginx.conf文件在打包应用时会拷贝到容器中,作为nginx启动的配置。

app目录下有三个文件,分别是:app.py、requirements.txt和uwsgi.ini。我们唯一不熟悉的就是requirements.txt,这个文件用来存放我们Python应用所需要的库,如flask、flask_sqlalchemy等等。在打包应用时会执行pip命令读取这个文件的内容,安装我们所需要的库。

这里,我们打印下requirements.txt的内容:

[root@ app]# cat requirements.txt
flask
flask_sqlalchemy

  

app.py文件也略做修改,新增两个路由/hello和/world:

from flask import Flask

app = Flask(__name__)

@app.route('/hello')
def hello():
return 'Hello!!!\n' @app.route('/world')
def world():
return 'World!!!\n' @app.route('/')
def hello_world():
return 'Hello World!!!\n' if __name__ == '__main__':
app.run()

  

上一章中,我们在uwsgi.ini文件中将uwsgi-socket配置绑定到本机的9000端口,同时在nginx.conf文件中设置uwsgi_pass,将请求转发到9000端口,这样的做法显得有些累赘,如果以后我不想用9000端口,意味着我需要改两个地方。那么,有没有办法让uwsgi自动获取绑定到一个端口,而nginx.conf又能获取到uwsgi所绑定的端口呢?肯定是有的:

uwsgi.ini

[uwsgi]
uwsgi-socket = /tmp/uwsgi.sock
chmod-socket = 777
callable = app
plugin = python3
wsgi-file = app.py
buffer-size = 65535
processes = %(%k * 2)
threads = %(%k * 20)
disable-logging = true

    

上面的uwsgi.ini文件中,我们不再将uwsgi-socket这个配置项绑定到特定的一个端口,而是指定了一个文件,这个文件是Unix套接字,即通过文件系统(而非网络地址)进行寻址和访问的套接字。配置uwsgi-socket之后,还需要配置chmod-socket,Unix socket是个文件,所以会受到Unix系统的权限限制,可以配置成660或者777,使得uwsgi客户端能够访问这个Unix socket文件,这里配置为777。

这里新增两个优化参数:processes和threads,分别是开启的进程数和线程数,而%k是魔数变量,代表CPU核数,如果我们是双核CPU,那这里的processes和threads分别为4和40,即有4个进程,每个进程有40个线程。disable-logging的意思一目了然,代表不记录请求信息的日志,只记录错误以及uwsgi内部消息到日志中。

最后,我们再来看下nginx.conf需要做改动的地方,其实也就是http模块下的server:

server {
listen 6666;
charset utf-8;
client_max_body_size 75M;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/uwsgi.sock;
……
}
}

  

其实改动的地方也只有一个uwsgi_pass,原先我们是直接绑定在9000端口上,而现在我们要指向uwsgi-socket所指向的Unix套接字。这样,nginx就可以自动将请求转发给uwsgi所监听的套接字了。

这里给出nginx.conf全部的内容:

user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 20480; events {
use epoll;
worker_connections 20480;
multi_accept on;
} 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"';
#请求量级大建议关闭acccess_log
#access_log /var/log/nginx/access.log main; sendfile on;
#tcp_nopush on; keepalive_timeout 300s;
client_header_timeout 300s;
client_body_timeout 300s; gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_types text/html application/javascript application/json; include /etc/nginx/conf.d/*.conf; server {
listen 6666;
charset utf-8;
client_max_body_size 75M;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/uwsgi.sock;
uwsgi_send_timeout 300;
uwsgi_connect_timeout 300;
uwsgi_read_timeout 300;
}
}
}

  

最后,我们来看下用于打包应用的Dockerfile:

# 使用基础镜像库
FROM moshangguang/nginx_uwsgi_py3:alpine3.8 # 创建工作路径
RUN mkdir /app # 指定容器启动时执行的命令都在app目录下执行
WORKDIR /app # 替换nginx的配置
COPY nginx.conf /etc/nginx/nginx.conf # 将本地app目录下的内容拷贝到容器的app目录下
COPY ./app/ /app/ # pip读取requirements.txt内容安装所需的库
RUN pip install -r /app/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package --no-cache-dir # 启动nginx和uwsgi
ENTRYPOINT nginx -g "daemon on;" && uwsgi --ini /app/uwsgi.ini

  

上面的每一条命令都有注释,这里就不再多作介绍了。

现在,让我们来打包web_app应用吧!将工作目录移到web_app目录下,执行docker build命令,创建镜像:

[root@ web_app]# docker build -t web_app .
Sending build context to Docker daemon 24.58 kB
……
Successfully built 88212eefb0b4

查看刚刚创建的web_app镜像:

[root@ web_app]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
web_app latest 88212eefb0b4 About a minute ago 79.9 MB

  

根据镜像启动一个容器,容器内部的nginx监听的是6666端口,而宿主机则用9999端口接收请求,再转发到容器内部的6666端口:

[root@ web_app]# docker run -p 9999:6666 -d web_app
a8cd1104dfc994637011ebd9dd9160d62eab64b1c9bb6ceb9266c092eb425452

  

这里,测试容器内的应用是否能正常处理用户的请求:

到此为止,我们便完成了用Docker构建基础镜像,并打包应用了。

Docker构建nginx+uwsgi+flask镜像(二)的更多相关文章

  1. Docker构建nginx+uwsgi+flask镜像(一)

    前言 笔者之前是从事Java方面的工作,自从18年5月左右来到新的公司,接触到Python,被其简单优雅的语法风格深深吸引,同时,新公司也帮助笔者打开Docker世界的大门,让笔者体会到“一次打包,到 ...

  2. 使用 Docker 和 Nginx 打造高性能的二维码服务

    使用 Docker 和 Nginx 打造高性能的二维码服务 本文将演示如何使用 Docker 完整打造一个基于 Nginx 的高性能二维码服务,以及对整个服务镜像进行优化的方法.如果你的网络状况良好, ...

  3. Ubuntu下nginx+uwsgi+flask的执行环境搭建

    选择web framwork是个非常艰难的事情, 主要分为轻量级和重量级框架. 因为没有搭建站点这样的须要, 所以回避SSH, Django这样的框架, 而选择一个轻量级框架. 自己也比較青睐pyth ...

  4. 一次请求中,经过 nginx+uWSGI+flask应用程序搭建服务的执行过程

    Flask框架有自带的http server,但是缺点非常明显,并发能力,及时响应非常差,只适合开发时自测使用. 在我接触过的项目中,生产环境使用nginx+uWSGI+flask应用程序进行部署服务 ...

  5. nginx+uwsgi+flask 服务器配置

    注:每个机器,软件版本可能不一样,虽然网上有很多类似的帖子,但是我在搭建的时候遇到了不少的坑,此文仅供参考. 请求流程: 1.安装uwsgi uwsgi是一个应用服务器,非静态文件的网络请求就必须通过 ...

  6. Ubuntu下使用Nginx+uWSGI+Flask(初体验)

    Ubuntu 18.04,Nginx 1.14.0, uWSGI 2.0.17.1,Flask, 前言 Windows不支持uWSGI!为了上线自己的项目,只能选择Linux. 自己前面开发了一个Fl ...

  7. nginx+uwsgi+flask+supervisor 项目部署

    环境 - Linux: Ubuntu 16.04 - uWSGI 2.0.18 - Flask 1.0.2 - supervisor 3.2.0 - nginx/1.8.1 首先区分几个概念 WSGI ...

  8. 用Docker构建Nginx镜像

    1构建Nginx镜像 1建立工作目录 [root@localhost ]# mkdir 1nginx [root@localhost 1nginx]# cd 1nginx/ [root@localho ...

  9. 服务器配置:ECS+Nginx+uWSGI+Flask——各部分详细介绍

    希望在阿里云ECS上搭建一个flask框架的web应用,经典的形式便是flask+uWSGI+nginx模式 服务器:CentOS 7.3 python版本:3.8.0 先贴一张全局图,这张图很清楚的 ...

随机推荐

  1. lucene的使用与优化

    1 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品.因此它并不像www.baidu.com 或者google Desktop那么拿来就能用,它只是提供了一种工 ...

  2. selenium学习备忘

    在做web项目的自动化端到端测试时主要使用的是Selenium WebDriver来驱动浏览器.Selenium WebDriver的优点是支持的语言多,支持的浏览器多.主流的浏览器Chrome.Fi ...

  3. Vue.js-创建Vue项目(Vue项目初始化)并不是用Webstrom创建,只是用Webstrom打开

    我犯的错误:作为vue小白,并不知道还要单独去创建初始的vue项目,于是自己在webstrom中建了一个Empty Project, 在其中新增了一个js文件,就开始import Vue from “ ...

  4. Node.js-Webstorm2018配置nodejs

    网上都是webstorm老版本的设置方法!根本就找不到以下配置项: 下面介绍2018版的配置方式.功能:使webstrom支持node.js语法检测及语法提示! 例如:配置前,没有任何提示 配置后 配 ...

  5. 【2017-07-01】Linux应用开发工程师面试问题记录之二:关于结构体的大小及内存对齐问题

    Tencent后台服务器开发有一道题是计算一个结构体的sizeof的大小: struct strData { int m_Int; char m_Char; short m_Short; char m ...

  6. 【LOJ6043】「雅礼集训 2017 Day7」蛐蛐国的修墙方案(搜索技巧题)

    点此看题面 大致题意: 给你一个长度为\(n\)的排列\(p\),要求构造一个合法的括号序列,使得如果第\(i\)个位置是左括号,则第\(p_i\)个位置一定是右括号. 暴搜 很容易想出一个暴搜. 即 ...

  7. P1567 统计天数

    题目背景 统计天数 题目描述 炎热的夏日,KC非常的不爽.他宁可忍受北极的寒冷,也不愿忍受厦门的夏天.最近,他开始研究天气的变化.他希望用研究的结果预测未来的天气. 经历千辛万苦,他收集了连续N(1& ...

  8. P1089 津津的储蓄计划

    题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在 ...

  9. 正则表达式 /i /g /m /ig /gi

    正则表达式中/i,/g,/ig,/gi,/m的区别和含义   /i (忽略大小写) /g (全文查找出现的所有匹配字符) /m (多行查找) / /ig(全文查找.忽略大小写) 

  10. (python)剑指Offer:数组中重复的数字

    问题描述 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1, ...