序
因为某些原因,写了个新闻聚合的应用,取名SCURSS ,这里想分享的是用容器进行虚拟化的思路
容器
具体内容就是一个爬虫定期爬取教务处,计算机学院官网,学工部,然后检查新闻内容是否发生了变化,如果发生了变化,那么更新数据库,然后邮件推送给订阅的用户发生更新了的消息
这里想说的是用的docker
来部署的服务, 虽然这不是什么新鲜的东西,但是我还没处理过这么多的容器之间的依赖关系,所以简单记录一下。因为这里需要的容器比较多,为了方便管理,使用了docker-compose
来进行编排
项目的文件目录如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ tree
.
├── database
│ └── Dockerfile
├── docker-compose.yml
├── Dockerfile
├── feed_gen
├── init_send
│ └── Dockerfile
├── send_mail
├── spider
├── wait-for-it.sh
└── web
└─ Dockerfile
容器编排
首先是写一个docker-compose.yml
内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
version: "3"
services:
pgsqldb:
image: postgres:10.1
container_name: pgsqldb
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: xxxxx
scurss_web:
build:
context: .
dockerfile: ./web/Dockerfile
container_name: scurss_web
restart: always
ports:
- "8000:80"
volumes:
- ./web/:/var/www/html/
depends_on:
- pgsqldb
- init_mail_server
mail_redis:
image: redis
container_name: mail_redis
restart: always
init_mail_server:
build:
context: .
dockerfile: ./init_send/Dockerfile
container_name: init_mail_server
volumes:
- ./init_send:/app
depends_on:
- mail_redis
- pgsqldb
restart: always
manage_python:
build:
context: .
dockerfile: Dockerfile
container_name: manage_python
volumes:
- .:/scurss
working_dir: /scurss
restart: always
depends_on:
- mail_redis
- pgsqldb
command: ["./wait-for-it.sh", "pgsqldb:5432", "--", "python", "manage.py"]
pgsqldb
,这是一个postgres
的数据库,用来存储爬虫获取到的内容,端口映射出来方便调试,上线了之后可以去掉端口映射,直接使用容器互联,同时在环境变量中把容器的密码传了进去scurss_web
这个是web容器,最开始是用的纯php容器,后来觉得懒得麻烦,直接搞了个带apache的,把目录挂载到/var/www/html
就能用了,当然这个潜在的问题就是整个web目录都暴露在里面了,比如Dockerfile
就可以直接访问到,当然我可以选择不把Dockerfile
放到这个目录,./web/Dockerfile
内容如下
1
2
3
4
5
6
7
8
FROM php:5.6-apache
MAINTAINER SCURSS
RUN apt update && apt install php5-pgsql libpq-dev -y --no-install-recommends \
&& docker-php-ext-install pdo pdo_pgsql pgsql
EXPOSE 80
因为web需要用到postgresql
,所以需要php
的psql
的支持,网上搜寻一圈找到了需要安装的包,这里只有自己写Dockerfile
来加入这些文件了
init_mail_server
这个容器是一个flask
程序的容器,用于监听是否有用户提交订阅信息,php
负责处理用户提交的POST
请求然后把订阅的内容插入到数据库中,然后通过一个get
请求通知flask
写的一个api
,然后flask
程序会去数据库取出来当前的所有的用户的信息,然后去redis
数据库中取出用户注册之前的用户列表,通过两个列表的存在差异的用户来确定哪一些是新注册的用户,然后去postgres
中取出每一个站点的最新的十条新闻,推送到用户的邮箱,这里因为需要用到自定义的python
包,所以自己写了Dockerfile
, 路径是./init_send/Dockerfile
,内容如下
1
2
3
4
5
6
ROM tiangolo/uwsgi-nginx-flask:python3.6
MAINTAINER scurss [email protected]
RUN pip install redis==2.10.6 arrow==0.10.0 psycopg2==2.7.3.2
mail_redis
这个是一个redis
的服务器,不对外开放端口,这里开放是方便我调试,上线后会关闭,不然又是一个妥妥的redis
未授权manage_python
是项目主程序的容器,执行的入口是python manage.py
然后会调用一系列的模块完成新闻爬取,内容更新比较,邮件推送,生成feed.xml
文件到web
目录等功能,由于这个程序一旦启动就需要连接到postgres
数据库,所以第一次我是启动失败了的,然后网上搜了下,看到了wait-for-it.sh
这个东西,以前其实也见到过,但是不是很了解他的功能,刚好今天有这个需求,所以大概了解了一下,他是通过监听互联的容器的端口来检测服务是否启动的,如果对应的端口起来了,那么就可以判断容器是已经完成启动了,然后就会执行后面的入口程序。 主程序的Dockerfile
如下
1
2
3
4
5
6
7
8
FROM python:3.6.3-jessie
MAINTAINER SCURSS
RUN pip install psycopg2==2.7.3.2 arrow==0.12.0 redis==2.10.6 pyrss2gen==1.1 \
lxml==4.1.1 requests==2.11.1 ipython==6.2.1 -i https://pypi.douban.com/simple
需求很简单,今晚就上线,怎么实现我不管
那么就用开发机吧
只要在任意的配置好了docker和docker-compose的地方,都可以直接运行整个项目
1
$ docker-compose up -d
所有的搭建环境的事情,我们都不需要关心,不用关心这是CentOS还是Ubuntu,或者是Debian
因为80端口不能只挂这一个服务,所以自然用了nginx来反代web,
在/etc/nginx/conf.d/scurss.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80; server_name scurss.les1ie.com;
access_log /var/log/nginx/scurss_access.log;
error_log /var/log/nginx/scurss_error.log;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
然后去dns
里面加入一条scurss.les1ie.com
解析到开发机
跋
最近事情太多了忙不过来,几个项目同时在赶工期,一天到晚敲敲敲,头晕
以后还是不要去当开发了,开发这个岗位不好呆,还是产品经理好玩
另外:
发现我真好满足,能有两个高分屏,椅子舒服,当然机械键盘也是要的,我的laji笔记本是1366*768的,看着太难受了(我真好收买,给个高分屏就行)
睡觉睡觉
2017年12月10日01:13:52