提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、无网的正式环境中实现docker部署
无网的环境不能用pip或from命令从网络上下载相关的引用包,需要在有网的环境中生成镜像并打包,再在正式环境中导入使用。实践过程中发现如果需要在正式环境中不断调试代码,反复的打包导入很麻烦,所以只在有网环境中把代码需要的环境打包,再在正式环境中引用环境包,方便调试代码。
1. 在有网的linux环境中下载相关包并打包
将程序需要的相关包写入Dockerfile中,如下包含python版本及相关包,使用了清华镜像加速下载
FROM python:3.9-slim
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy==1.23.5 \
pandas==1.5.3 \
scipy==1.10.1\
pymysql \
sqlalchemy==1.4.32 \
openpyxl \
xlsxwriter
找一台有网的电脑,运行该Dockerfile,其中docker只支持linux环境,windows系统可以使用虚拟机,以下命令运行同目录的Dockerfile生成了一个名为cameraenv的镜像:
docker build -t cameraenv .
将cameraenv镜像打包为tar包:
docker save -o /media/sf_Drone/out/cameraenv.tar cameraenv
2. 在正式环境中导入环境包
将生成的tar包复制到正式环境中并导入:
docker load -i cameraenv.tar
查看镜像是否导入成功:
docker images
3. 生成包含代码的镜像
我程序的代码结构如图
其中包含的Dockerfile如下:使用cameraenv镜像中包含的环境;生成/home主工作目录,其下又包含/code和/out两个目录,上图主机中目录中的所有文件会复制到/code目录中;并执行“python /home/code/camera_fault.py”的命令运行python脚本,Dockerfile中只能包含一条CMD命令,也可以在运行镜像后,进入容器中手动执行该python命令。
FROM cameraenv
COPY . /home/code
RUN mkdir /home/out
WORKDIR /home
CMD ["python", "/home/code/camera_fault.py"]
在该Dockerfile同目录下运行docker build命令生成名为camerafault的镜像:
docker build -t camerafault .
生成并运行一个基于camerafault镜像的container:–name 表示给容器取名,不写会自动生成一个名字;-ti 表示为容器分配一个伪输入终端并以交互模式运行容器,这样容器里程序的输出主机里能看到,方便调试; -v 表示目录或文件的挂载,将主机的/home/yanf/out/目录挂载到镜像的/home/out/目录中,为了让容器里程序的输出能同步到主机上,挂载是双向的;–privileged 表示给容器完整权限。
docker run --privileged -ti -v /home/yanf/out/:/home/out/ --name contain1 camerafault
程序结束后会自动退出容器,执行以下命令查看所有容器,不加-a 则只显示在运行的容器,
docker ps -a
可以看到名为contain1的容器,基于镜像camerafault,状态是Exited退出,若想容器退出后自动清除,可以在使用
docker run命令时加上 --rm 选项。
要删除镜像需要先清除所有使用它的容器。
docker rm 7c7f413cd520 #删除容器
docker rmi 0cd7ee66df09 #删除镜像
二、Docker中利用crontab启动定时任务
想要实现定时执行某一python脚本,有两个思路,一是使用系统的crontab命令,将定时任务指令写在Dockerfile里让系统去调度python脚本;二是使用python包如apscheduler,写一个主程序来定时调度python脚本。这里分享方法一,方法二取决于使用的python包。
1. 安装crontab
docker中要使用cron需要先安装,在有网的环境中安装环境包时额外加上如下命令,安装crontab和tzdata,tzdata用于修改docker容器的时区,docker默认是UTC+0时区。rm和clean用于减小镜像体积。
RUN apt-get update \
&& apt-get install -y --no-install-recommends cron \
&& apt-get install -y tzdata \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean
2. Docker中使用crontab调度python脚本
在正式环境中,修改Dockerfile如下:
FROM cameraenv
COPY . /home/code
RUN mkdir /home/out
WORKDIR /home
ENV LC_ALL C.UTF-8
ENV TZ=Asia/Shanghai
RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
RUN echo "*/2 * * * * root python /home/code/camera_fault.py >> /home/out/log.txt" >> /etc/crontab
CMD PYTHONIOENCODING=utf-8 /etc/init.d/cron start && touch out/log.txt && tail -f out/log.txt
*/2 * * * * root python /home/code/camera_fault.py >> /home/out/log.txt
即 cron定时命令,表示每两分钟运行python脚本,并将程序运行的输出写入到log.txt;echo string >> /etc/crontab
表示将该定时命令配置到crontab服务中,如有多个python脚本,同样可以用echo命令写入服务,多条命令用&&
连接。
/etc/init.d/cron start
表示启动crontab服务。
tail -f out/log.txt
表示追踪文件尾部内容的变化并显示更新,直到被中断或退出,这条命令很重要,原因在下一节。
剩下的命令用于修改容器的timezone为Asia/Shanghai时区。
同样利用docker build生成镜像,docker run运行容器结果如下:
运行后使用Ctrl+P+Q退出容器并让容器在后台保持运行,若使用ctrl+C会退出并中断容器。
想再次进入运行的容器,使用docker attach containerid
重新进入。
三、 Docker中使用crontab常见问题
1. cron服务启动后立即结束
即输出Starting periodic command scheduler: cron
后容器就退出了,如果没有使用tail -f out/log.txt
命令会出现这个情况,因为定时命令没到点没执行,docker认为程序已经执行完结束并退出了,而tail -f
命令则会让系统一直监视日志文件,容器就不会退出。
2. cron服务启动后一直挂起
即输出Starting periodic command scheduler: cron
后,容器到点没有启动定时任务但也不退出容器,一直是挂起的状态,原因是程序出错了,但不会报错,就会给人感觉crontab服务一直挂起的感觉。
所以建议先不用crontab,保证代码正确后,再加crontab;另外如果代码单独执行正确,但加上crontab服务后出错,可以看看是不是相关文件名使用了相对路径,使用crontab时程序里的文件名需要是绝对路径。