阿里云高性能服务器2折起:点我购买
近期有两个flask小项目需要部署在阿里云服务器上,最终成功使用docker完成部署,中间踩了不少坑,特此记录下来,希望帮助别的同学少踩坑。
服务器是阿里云Ubuntu 14.04.5 LTS,使用nginx+gunicory部署,supervisor监控程序。
这里重点说下docker部分,关于docker教程,推荐这个:Docker-从入门到实践
不熟悉docker的同学务必看下相关教程,docker相关安装及如何加速这里我不赘述了,只对我用到的即部署环节所需要注意的进行说明。
我的Dockerfile如下:
FROM ubuntu:16.04
LABEL maintainer="BlackRun"
ENV PYTHONIOENCODING=utf-8
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& apt-get clean \
&& apt-get update \
&& apt-get install -y python3-pip python3-dev nginx supervisor\
&& rm -rf /var/lib/apt/lists/*
ADD pip.conf /etc/pip.conf
COPY supervisord.conf /etc/supervisord.conf
COPY supervisor.conf /etc/supervisor/
RUN pip3 install --upgrade pip
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt \
&& ln -s /app/nginx.conf /etc/nginx/conf.d \
&& rm -rf /etc/nginx/sites-enabled/default \
&& rm -rf /etc/supervisor/supervisord.conf \
&& sed -i 's/nodaemon=false/nodaemon=true/g' /etc/supervisord.conf
EXPOSE 9001
EXPOSE 9002
CMD ["supervisord", "-c", "/etc/supervisord.conf"]
下面一一作出说明:
前三行,说明了基础镜像使用官方的ubuntu:16.04、作者名、设置PYTHONIOENCODING变量名
这里需要注意的是,根据教程,Docker每有一个RUN就会多一层镜像,所以应该避免使用RUN命令。具体请查看前面给出的教程。
sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
两行命令,设定ubuntu的apt源为阿里源,加快下面下载所需依赖的速度。其中sed是linux下一种在线编辑器。
apt-get clean \
apt-get update \
apt-get install -y python3-pip python3-dev nginx supervisor\
rm -rf /var/lib/apt/lists/*
这四行对apt进行更新,安装依赖,最后删除相关包,节省空间,熟悉ubuntu的同学应该都理解
ADD pip.conf /etc/pip.conf
COPY supervisord.conf /etc/supervisord.conf
COPY supervisor.conf /etc/supervisor/
RUN pip3 install --upgrade pip
我习惯使用阿里源从python库中下载文件,所以使用pip.conf添加阿里源。2、3行是复制supervisor相关配置文件进image文件里,最后一行更新pip.
pip.conf
[global]
trusted-host=mirrors.aliyun.com
index-url=http://mirrors.aliyun.com/pypi/simple
supervisor.conf
[program:nginx-app]
command = /usr/sbin/nginx -g "daemon off;"
stdout_logfile = /var/log/supervisor/nginx_stdout.log
stdout_logfile_maxbytes = 10MB
stderr_logfile = /var/log/supervisor/nginx_error.log
stderr_logfile_maxbytes = 10MB
[program:student_filter_gunicorn]
command = /usr/local/bin/gunicorn -w 4 -b 127.0.0.1:8002 app:app
directory = /app/student_filter
stdout_logfile = /var/log/supervisor/student_filter_gunicorn_out.log
stdout_logfile_maxbytes = 10MB
stderr_logfile = /var/log/supervisor/student_filter_gunicorn_error.log
stderr_logfile_maxbytes = 10MB
[program:xueji_gunicorn]
command = /usr/local/bin/gunicorn -w 4 -b 127.0.0.1:8003 app_mac:app
directory = /app/xueji
stdout_logfile = /var/log/supervisor/xueji_gunicorn_out.log
stdout_logfile_maxbytes = 10MB
stderr_logfile = /var/log/supervisor/xueji_gunicorn_error.log
stderr_logfile_maxbytes = 10MB
这里使用gunicorn监听8002和8003两个端口运行python应用,然后用nginx作反向代理。
添加日志文件,是为了方便调试,不加也行。
具体supervisor使用教程可以查看我以前的文章supervisor使用小计
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt \
&& ln -s /app/nginx.conf /etc/nginx/conf.d \
&& rm -rf /etc/nginx/sites-enabled/default \
&& rm -rf /etc/supervisor/supervisord.conf \
&& sed -i 's/nodaemon=false/nodaemon=true/g' /etc/
再回到Dockerfile中,上面命令第一行将当前目录下所有文件复制到容器的/app目录下。然后用WORKDIR命令说明工作目录(相当于运行 cd /app)
下面3-7行,分别是安装我的项目用到的python库,建立nginx配置文件的软链接,然后删除nginx和supervisor默认配置文件,将supervisor配置为后台运行。
rm -rf /etc/nginx/sites-enabled/default
其中有个大坑就是上面这句一定要有,因为默认配置文件监听了80端口,如果你在配置文件里也监听80端口,导致你访问80端口时候只会显示nginx的欢迎界面。
EXPOSE 9001
EXPOSE 9002
CMD ["supervisord", "-c", "/etc/supervisord.conf"]
最后三行,声明运行容器时提供的服务端口以及运行supervisord命令,将整个应用拉起来运行。
因为项目很小所以我的nginx.conf很简单,需要其他功能的同学请自行添加
nginx.conf
server {
listen 9002;
server_name 127.0.0.1;
location / {
proxy_pass http://127.0.0.1:8002;
}
}
server {
listen 9003;
server_name 127.0.0.1;
location / {
proxy_pass http://127.0.0.1:8003;
}
}
最后运行在Dockerfile目录下运行下面命令即可生成容器,一切顺利的话就可以在浏览器里访问到你的应用了。
docker image build -t flask .
docker container run --name flask -d -p 9002:9002 -p 9003:9003 flask
我还用到了阿里云提供的镜像服务,建立了自己的镜像仓库,将本地生成好的image推送到阿里云镜像仓库,然后在云服务器上再拉取下来,方便快捷。具体可以看:阿里云容器镜像服务,目前是免费的。当然你也可以推送到docker官方的仓库。
下面简单说下踩的坑和一些排错技巧:
一、上面提到的一定要删除nginx的默认配置文件。
二、在ubuntu上安装docker不要使用apt-get安装,使用下面命令安装
sudo curl -sSL https://get.docker.com/ | sh
三、docker官方的ubuntu镜像,少了很多东西,不方便调试,所以可以在容器中使用下面命令安装一些常用的工具:
apt-get update
apt-get install -y lsof net-tools curl vim
然后结合相关的日志就可以排错。
我最后在阿里云服务器上拉取镜像后,发现通过浏览器仍然无法访问程序,这时候可以用docker exec 命令进入到容器里,然后运行下面命令:
curl http://127.0.0.1:8002
curl http://127.0.0.1:9002
我的返回了正确的html代码,说明我的部署没有问题,看了下阿里云服务器,我的是专有网络,在安全组里打开9002和9003即可正常访问。