Flask+Nginx博客容器化部署

Flask博客部署到云服务器完整流程

我是一个爱折腾的人,2016年才开始学会自建博客,到现在博文没写多少篇却折腾了好几回。经历了Hexo+GitHub Page,再到Flask+Heroku,现在终于用上了国内云服务+Nginx,感觉速度快了很多。总结起来,使用Flask+Nginx,好处有以下几个方面:

  • DIY程度高,现在我用的自己开发的Markdown引擎,非常方便扩展,在此推荐一下:Marko
  • 依靠Nginx强大的反向代理,现在我终于不用到处存图片然后贴一个巨长的URL了,直接映射到/images/下,干净整洁。
  • HTTPS支持,可以用云服务购买的免费证书,也可以用Letsencrypt,甚至可以用自签名证书。

我之前部署Flask的网站一直都用的virtualenv,现在既然切到云服务器,就干脆换成用Docker了,隔离化程度更高,我也可以用现在最新版本的Python了。博客系统可拆分为三个部分:

  • Flask应用,负责处理请求,是系统的核心
  • 数据库
  • Nginx服务器

三个部分分别独立为一个容器。从一个全新的云服务器开始(以Ubuntu Server 16.04.1为例,其余系统类似),部署步骤如下:

0x00 添加用户

使用一个非root的用户是一个好习惯,需要自己添加:

# adduser fming
# echo "fming   ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers

然后切换到fming用户登录

0x01 安装Docker

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

此脚本将自动将Docker CE安装到系统上,若安装失败,可尝试其他安装方法。安装完成后,需添加当前用户到docker组:

$ sudo usermod -aG docker $USER

0x02 安装Docker-compose

Docker-compose是一款Docker的工具,它能让你高效管理多个容器,否则需要加一大堆选项到Docker命令后。它同样提供了一个一键安装脚本(其他安装方法):

sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

0x03 DockerDocker-compose配置

将仓库拷贝到云服务器上,在目录下新建Dockerfile文件:

# --------------------------
# Docker file
# --------------------------
FROM python:3.7

# -- Install dependencies
RUN pip install --upgrade pipenv

ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8

# Application
RUN mkdir /app
COPY . /app
WORKDIR /app

RUN set -ex && pipenv install --deploy --system

RUN chmod a+x start_server.sh

我使用Pipfile+Pipenv来管理依赖包,Pipenv是近年比较流行的Python包管理工具,它可以很方便地追踪更新、定性部署。当然你也可以用传统的pip+requirements.txt,只需要做对应修改即可。

start_server.sh是启动应用的脚本,我并未在Dockerfile中启动它,它将由Docker-compose负责管理启动。它的内容如下:

#!/bin/sh
# 升级数据库
flask db upgrade
# 编译翻译文件
make compile
# 启动服务,使用exec以防止另起进程
exec gunicorn -b :5000 --access-logfile - --error-logfile - -w 4 "wsgi:create_app()"

下一步,新建一个docker-compose.yml用来管理容器:

version: '3'

services:
  web:
    build: .
    command: bash ./start_server.sh
    env_file: .env
    volumes:
      - ./:/app
    ports:
      - "5000:5000"
    depends_on:
      - db

  db:
    restart: always
    image: postgres:10
    env_file: .env
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  nginx:
    restart: always
    image: nginx:stable
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/log:/var/log/nginx
      - ./nginx/cert:/opt/cert
      - ./flaskblog/static:/opt/static
    ports:
      - "80:80"
      - "443:443"

volumes:
  pgdata:

其中使用了volumes来将容器中的文件映射到本地,这样就不会随着容器的销毁而丢掉。其中除了pgdata外,都是映射到本地目录,我们需要新建一个名为pgdatavolume:

Bash
$ docker volume create pgdata

.env是一些相关的环境变量:

POSTGRES_USER=xxx
POSTGRES_PASSWORD=xxx
POSTGRES_DB=flog_db
DB_SERVICE=db
DATABASE_URL=postgresql+psycopg2://xxx:xxx@db:5432/flog_db
COS_SECRET_ID=xxx
COS_SECRET_KEY=xxx

使用db就可以指代数据库容器的服务地址了。

注意:.env./nginx/cert(证书目录)不可提交到版本控制平台上。

0x04 Nginx配置

在上一节的配置中可以看到我把Nginx的配置文件映射到了./nginx/conf.d/default.conf中。

主站

Nginx
location / {
	proxy_pass http://web:5000;
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

配置静态文件缓存

Nginx
proxy_temp_path /tmp/temp_dir;
proxy_cache_path /tmp/cache levels=1:2 keys_zone=mycache:100m inactive=1d max_size=10g;
server {
...
location /static {
	alias /opt/static;
	proxy_set_header Host $host;
	proxy_cache mycache;
	expires 30d;
}

我之前已经把静态文件映射到Nginx容器中的/opt/static了。

映射图床地址

Nginx
location ^~ /images/ {
	proxy_pass https://frostming-tencent-1252779928.cos.ap-guangzhou.myqcloud.com/;
	proxy_cache mycache;
}

这样,只要访问yourdomain.com/images/image1.jpg就能转到https://frostming-tencent-1252779928.cos.ap-guangzhou.myqcloud.com/image1.jpg了,注意location/images/的斜杠不可缺少。

0x05 启动容器

好了,万事俱备,现在可以启动容器了!转到仓库所在目录:

docker-compose up --build -d

拉取镜像,构建镜像,启动容器,一条命令足矣!一切都没有问题的话,你的网站已经跑起来了。

请参考此博客的GitHub获取完整配置

最后编辑于
知识共享协议
本作品采用CC-BY-SA许可.