今天是被docker虐的一天。任务是把自己用python写的flask服务部署到一个服务器上,悲剧的是那个服务器上没有python,不能联网。
尝试的第一个方法是装anaconda,把每个包下载到本地,然后逐个安装。这样的问题是:有的包依赖的包太多了,实在是装不过来,瞎折腾了很久才决定放弃这条路。如果您遇到这种情况,请一定不要学我,钻了半天的牛角尖才想到可以换个方法!
尝试的第二个方法是用docker,然后就开启了被docker虐的一天,所幸最后是成功了。
一、docker部署的流程
1.写dockerfile。
主要包括如下内容:
a)用到的基础镜像;
FROM base_imageb)把东西拷到工作空间中,
COPY myproject /workspace建工作空间;
WORKDIR /workspacec)启动程序
CMD python app.pyCMD:一个Dockerfile中只有一个CMD命令,是Docker镜像启动后Docker容器会默认执行的命令。
RUN:一个Dockerfile中可以有许多个RUN命令,可以改变Docker镜像
在Dockerfile中可以设置pip安装时所用的镜像,方法是在根目录下新建.pip文件,存放pip的配置
2.打包代码到镜像
docker build -t image_name:version .3.启动服务
docker run -itd --name=myproject -p 外部端口号:内部端口号 image_name:tag如果不出意外到这里,就可以直接访问flask服务了,如果出了意外,比方说出了bug,那么就需要接着看了
如果出了bug,那么先看看出了什么错,再补救一下,如果补救不回来,需要把原来的镜像删掉,然后重新搭
4.看log
先找到container_id
docker ps -a | grep 镜像名字(可以只是一部分)再查看log
docker logs [container_id]二、重新打docker镜像
1. 把docker容器stop掉
docker stop 容器id如果不知道容器id是多少,那么可以用,下面这个命令会提示你这个镜像下面有哪些容器没有关
docker image rm -f 镜像id然后再用docker stop把容器停掉。
2. 把原来的docker镜像删掉
docker image rm -f 镜像id至此,docker的镜像就删除完毕了
3. 导出docker镜像
docker save -o new_image_name.tar image_name:tag4.加载导出的docker镜像
docker load < new_image_name.tar加载进来之后找到对应的镜像id,因为刚刚载入的时候并没指定镜像的名字和tag,所以需要根据时间和size来判断载入的镜像
docker images三、 docker所在主机和docker容器之间传递文件
docker cp 主机目录 容器id:docker目录这个其实也是一个坑,原本我是把python中的一个包给改了,当然轻易我也不会改,然后以为应该建成docker镜像后再改容器,结果这样做并不对,然后就在Dockerfile中改了,用更改之后的文件替换原来的文件。方法是在Dockerfile中,装完包后,用COPY把更改后包,替换掉原来的包。
四、大文件传输
这绝逼是个大坑,原本我天真的以为现在科技这么发达,文件传输应该不是什么问题,too young too simple。这个问题整整耗了我一晚上。无比惨痛的教训啊:我的docker镜像有2.6g,需要从开发的服务器上下载下来,在传到跳板机上,在传到测试环境的服务器上。
我上传了3遍才发现文件太大上传到跳板机是不可能的事情,整整耗了我两个多小时!!!!
我压缩了tar文件,然后上传,速度还挺快的,挺好的。在传输之前可以压缩一下,gzip image_name.tar,然后传输压缩后的.gz 文件,载入时也可以直接载入.gz文件。
这个世界上总有我想不到的邪门。当你觉得世界已经够了的时候,他会告诉你,还能更恶心。
我的docker镜像终于安全到达了测试服务器,这时候,我要把docker镜像load进来,load了很久,大概半个小时吧,告诉我测试服务器没有空间了,我从来不知道人生可以这么艰难。
五、传递参数
会遇到在运行时需要指定运行环境,也就是在docker run...中指定参数,比如python app.py --mode=prod指定目前是在开发环境中运行,这种情况,可以在Dockerfile文件中用ENV
在Dockerfile中
ENV var_name var_default_valuevar_default_value是变量的默认值。
在运行时输入
docker run -p 外部端口号:内部端口号 -e var_name=var_value -d image_name:tag六、如果要看日志,可以用以下方式进入docker容器中
docker exec -it container-id bash如果不知道container-id,可以用
docker ps来查看container-id,
查看日志文件
cat logging.txt七、docker容器里的时间跟主机的时间不一样,尝试了改dockerfile的方法,但是因为需要安装东西,连不上网,就算了。后来用的方法是https://zhuanlan.zhihu.com/p/38405663?from_voters_page=true
思想是拷贝主机的时区信息到容器中,步骤很少,也很简单。为了方便之后查阅我就直接抄在这里了。
1)复制宿主机上的zoneinfo文件夹到容器下的/usr/share/
docker cp /usr/share/zoneinfo container_id:/usr/share/2)进入docker容器之中(进入方法参考本文第六部分),更改时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime echo "Asia/Shanghai" > /etc/timezone3)检验
date
应该就正常了吧……