docker 制作支持cron 调度 python image 遇坑全记录

一:需求

项目中需要用到docker,本次是为实时数据爬取做的定时调度docker image。但是python 开发工程师做的爬虫调度是依赖于操作系统的定时调度的,暂时也用不到像xxl-job 之类的定时调度框架。只能用操作系统的调度了。所以需求如下:

1.能有定时调度

2.支持python 环境

二:image 制作

v1 image

FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install python3-pip -y && \
    ln -s /usr/bin/pip3 /usr/bin/pip 
    

坑一:centos:latest 没有自带crond,安装了crond以后还有各种各样的问题,systemctl 不能使用 crond 不能自启动等等。所以选择ubuntu:18.04 作为base image。

因为ubuntu:18.04 自带了python 3.6.7 所以不需要安装,但是没有装pip 所以需要安装pip。

v2 image

python 工程师纠结于打包执行的问题,所以提出将整个目录拷贝到image 中 使用python3 crawl.py 来执行python脚本,所以需要用pip 安装基础的包,所属有的基础包都放到requirements.txt中(requirements.txt 参见https://docs.docker.com/get-started/part2/)。

FROM ubuntu:18.04

WORKDIR /crawl
COPY /crawl  /crawl

RUN apt-get update && \
    apt-get install python3-pip -y && \
    ln -s /usr/bin/pip3 /usr/bin/pip && \
    pip install -r requirements.txt
    

坑二:centos采用二进制形式安装python过程中遇到安装完成后pip 不能使用SSL的bug, 需要安装openssl 并在./configure 中添加参数 --with-ssl  。

v3 image

增加定时调度脚本

*/1 * * * *  python3 /crawl/crawl.py >> /var/log/crawl.log 2>&1

坑三:cron 或者是crond 运行是在系统后台执行,没有前端进程,如果用k8s 来编排服务的时候势必导致pod 无限重启。所以需要通过脚本记录日志,使用前端进程读取日志来作为docker container 、k8s pod存活的标记 。

FROM ubuntu:18.04

WORKDIR /crawl
COPY /crawl  /crawl

RUN apt-get update && \
    apt-get install python3-pip -y && \
    ln -s /usr/bin/pip3 /usr/bin/pip && \
    pip install -r requirements.txt && \
    crontab /crawl/crontabfile

CMD  tail -f /var/log/crawl.log 

三:测试(正式爬坑)

build 

docker build --tag=test:v1 .

run 

docker run --it test:v1 /bin/bash

坑四:进入terminal后发 cron ,rsyslog 服务启动不了,cron log日志没有记录。手动启动cron 服务。service cron start

坑五:手动执行python 脚本。python3 crawl.py 抛出异常  UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-11: ordinal not in range(128) 中文编码的问题。通过各种google以后找到合适的解决方案:

# locale -a

C
C.UTF-8  //支持中文
POSIX

修改编码 export LANG=C.UTF-8


坑六:程序是可以执行了,但是发现时间不对,默认时区不正常。

TZ=Asia/Shanghai
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
apt-get install tzdata
dpkg-reconfigure --frontend noninteractive tzdata

 

坑七:python 结果重定向不能实时输出问题。python 重定向模式默认是带缓存区的,需要执行时指定 python3 -u crawl.py

或者是设置参数PYTHONUNBUFFERED=1。我采用的方式是。

export PYTHONUNBUFFERED=1

坑八:cron 调度的时候 python 程序不执行,每次都打印几行以后就不再打印了(这是本次docker image 中坑最大的一个)。

具体原因呢是因为cron 不认识/etc/profile ~/.bashrc,对cron。

The cron daemon was designed in such a way that it does NOT execute commands within your normal shell environment. This means you cannot use bare commands in cron the way you would from the SSH shell command line. This is because the PATH environment variable is /usr/bin:/bin, and the SHELL environment variable is set to /bin/sh

原文链接 https://help.dreamhost.com/hc/en-us/articles/215767107-Execution-environment-of-a-cron-job

 

*/1 * * * * . /etc/profile; python3 /crawl/crawl.py >> /var/log/crawl.log 2>&1

 

至此采坑完毕:final image

 

FROM ubuntu:18.04

WORKDIR /crawl
COPY /crawl  /crawl

ENV TZ=Asia/Shanghai
ENV LANG=C.UTF-8

RUN apt-get update && \
    apt-get install python3-pip -y && \
    ln -s /usr/bin/pip3 /usr/bin/pip && \
    pip install -r requirements.txt && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
    apt-get install tzdata -y && \
    dpkg-reconfigure --frontend noninteractive tzdata && \
    echo 'export PYTHONUNBUFFERED=1' >> /etc/profile && \
    echo 'export LANG=C.UTF-8' >> /etc/profile && \
    crontab /crawl/crontabfile

CMD  service cron restart && echo `date` >> /var/log/crawl.log && tail -f /var/log/crawl.log 

final crontabfile 

*/1 * * * * . /etc/profile; python3 /crawl/crawl.py >> /var/log/crawl.log 2>&1

 

你可能感兴趣的:(docker,image,cron,ubuntu:18.04)