在Docker中部署Python项目,以及压缩Docker镜像大小

一、创建docker目录:

      在目录下面新建三个文件:Dockerfile,项目文件,requirements.txt

Dockerfile文件内容格式如下:

# 基于镜像基础
#FROM python:3.6
FROM python:3.6-slim-stretch    #有更小的体积
 
# 维护者信息
MAINTAINER name [email protected]
 
# 复制当前代码文件到容器中 /app
ADD . /app
 
# 设置app文件夹是工作目录 /app
WORKDIR /app

#解决Dockers中打印日志不及时的问题
ENV PYTHONUNBUFFERED=0
 
# 安装所需的包,默认为使用python官方镜像源,安装 比较慢
#RUN pip install -r requirements.txt
#可以修改为清华源
RUN pip install -r requirements.txt - i https://pypi.tuna.tsinghua.edu.cn/simple
  
# Run test.py when the container launches
CMD ["python", "/app/test/test.py"]

项目文件:直接把完整项目拷贝到docker目录下面
项目依赖:requirements.txt文件

python 项目自动生成requirements.txt文件的方法有两种

1、进入需要生成文件的目录,执行 pip freeze > requirements.txt ,此方法会包含环境所有的依赖包。

2、pip install pipreqs

进入需要生成文件的目录执行: pipreqs ./ (或者直接 pipreqs D:\test(实际路径))

在此时可能会遇见

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0x80 in position 776: illegal multibyte sequence

这个错误.

解决方法:指定编码格式 pipreqs ./ --encoding=utf8

二、生成镜像

# 1.进入docker文件夹
[root@localhost ~]# cd /www/wwwroot/docker
 
# 2.创建镜像(命令中最后的点不要忘记,这里表示当前目录,也可以写绝对路径)
    # -t :指定要创建的目标镜像名
    # . :Dockerfile文件所在目录,可以指定Dockerfile 的绝对路径
[root@localhost ~]# docker build -t imagename Dockerfilepath
[root@localhost ~]# docker build -t test .
[root@localhost ~]# docker build -t li /www/wwwroot/docker

三、查看镜像是否生成


# 查看所有镜像
[root@localhost ~]# docker images

四、运行镜像程序,生成并启动容器

# 前台运行一个镜像,生成新的container(运行一个交互式的container容器)
[root@localhost ~]# docker run -it -p 8080:9060 --name ef_nfcs ef_nfcs_img 
 
# 后台运行一个镜像,生成新的container
[root@localhost ~]# docker run -d -p 8080:3000 --name c_name imagename
[root@localhost ~]# docker run -d -p 8080:3000 --name test li
 
# 宿主机的端口和容器端口的映射关系是:8080:3000(docker中部署的项目端口就是3000)
# 访问:http://宿主机ip:8080/index 即可。
# 映射宿主机的 8080 端口到docker容器的 3000 端口。

五、Docker基本命令

# 查看所有的容器(不加-a:查看当前正在运行的容器的详情)
[root@localhost ~]# docker ps -a
 
# 删除容器:
[root@localhost ~]# docker rm 容器ID
 
# 进入容器
[root@localhost ~]# docker exec -it 容器ID /bin/bash
[root@localhost ~]# docker exec -it a6e3963fd253 /bin/bash
[root@localhost ~]# docker attach 容器名或容器ID

#查看容器日志,通过docker logs命令可以查看容器的日志。
$ docker logs [OPTIONS] CONTAINER
  Options:
        --details        显示更多的信息
    -f, --follow         跟踪实时日志
        --since string   显示自某个timestamp之后的日志,或相对时间,如42m(即42分钟)
        --tail string    从日志末尾显示多少行日志, 默认是all
    -t, --timestamps     显示时间戳
        --until string   显示自某个timestamp之前的日志,或相对时间,如42m(即42分钟)

 #查看指定时间后的日志,只显示最后100行:
$ docker logs -f -t --since="2018-02-08" --tail=100 CONTAINER_ID

#查看最近30分钟的日志:
$ docker logs --since 30m CONTAINER_ID

#查看某时间之后的日志:
$ docker logs -t --since="2018-02-08T13:23:37" CONTAINER_ID

#查看某时间段日志:
$ docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37" CONTAINER_ID  
 
# 退出容器
# 使用Ctrl + P + Q退出容器,就不会中断工程,等于退出容器后,还可访问容器的工程,再进入,也是使用命令:docker attach  容器ID
# ctrl+d   退出容器且关闭, docker ps 查看无
# ctrl+p+q 退出容器但不关闭
 
# 附加:进入容器中,安装jdk和tomcat的步骤和在linux中安装步骤一致,你可以把容器当成一个linux虚拟机。

进入容器:
docker exec -it 容器ID sh
查看容器中日志文件:
tail -f -n 2000 (文件名)

1、从容器里面拷文件到宿主机?
docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径

 示例: 假设容器名为testtomcat,要从容器里面拷贝的文件路为:/usr/local/tomcat/webapps/test/js/test.js,  现在要将test.js从容器里面拷到宿主机的/opt路径下面,     :在宿主机上面执行命令

docker cp testtomcat:/usr/local/tomcat/webapps/test/js/test.js /opt
2、从宿主机拷文件到容器里面
docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径

   示例:假设容器名为testtomcat,现在要将宿主机/opt/test.js文件拷贝到容器里面的/usr/local/tomcat/webapps/test/js路径下面,在宿主机上面执行如下命令     

docker cp /opt/test.js testtomcat:/usr/local/tomcat/webapps/test/js
3、在这里在记录一个问题,怎么看容器名称?

  执行命令:docker ps,,其中NAMES就是容器名了。

4.需要注意的是,不管容器有没有启动,拷贝命令都会生效。

六、docker镜像导出

,tar镜像包可以拷贝到其他机器docker环境中加载

docker save test -o test.tar

七、docker镜像加载

docker load -i test.tar

八、docker 删除镜像

docker删除一个镜像必须先删除此镜像中运行的容器,要删除容器,必须 先停止容器,所以删除镜像的步骤为:

docker  stop 容器ID
docker rm 容器ID
docker rmi 镜像ID(镜像名)

九、删除none镜像

删除none的镜像,要先删除镜像中的容器。要删除镜像中的容器,必须先停止容器。

$ docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }')  #停止容器
1b7067e19d6f
a840f345c423
9d74eff1c4e4
17d361107a21
dd51ead96da7
ad0032609294
95e713ab1bdf
  
$ docker rm $(docker ps -a | grep "Exited" | awk '{print $1 }')  #删除容器
1b7067e19d6f
a840f345c423
9d74eff1c4e4
17d361107a21
dd51ead96da7
ad0032609294
95e713ab1bdf
  
$ docker rmi $(docker images | grep "none" | awk '{print $3}')  #删除镜像
Deleted: sha256:168b258ceea3f5ee9d7f066e04c89c4858f0e337687f18b5939a78aea13ea6c8
Deleted: sha256:d3984014bcbe856f569dcade31ce70aae8cc5ead3806e47ae08229467c9ed3ca
Deleted: sha256:b2c5d34941c646a1962d2acd9ff968708495a82916c33797f5fb3d94de403c6d
Deleted: sha256:5a23f5ad9107bb1111f32d490982e2146cf0811c8b75c7a6cd67ca45fc2f50dd
Deleted: sha256:392d616344b17b0bb7b8ad46cc9a8c6f5ab4be8bd59c3d5973016e8759a1668c
Deleted: sha256:33fbf9c999e8beac51b184a0f2baeaf1a2b99b10c4cc1f654075af42779fb62e
Deleted: sha256:b3535d64be668cd7e3389c4da224ae6e3aaedadff05ed24f428fc83e96c65a03
Deleted: sha256:da47261567b38193ba4894e7c832d9eba78d9cc3a501101ebf5fd7304efef5b9
Deleted: sha256:b81b2578fd4e803fac0bd416e606362ed14432370088eba8bf5c43a4fca8f7ed
Deleted: sha256:6f4b2f9fd5be471ac80c599c9616feaaf3952ce8a68d5d8c26645bfaff7aae4a
Deleted: sha256:480e2b77d27aea6e128db8d3c400f37b74da1b365b0eb663022d7208a9694209

十、如何压缩docker中Python镜像大小?

实际开发过程中,我们都是从dockerhub中拉取现有镜像,然后基于此构建自己的镜像,实际上,这样的操作虽然方便,但是带来的问题也很大。比如我们按照以上流程打包后的镜像大小在900MB以上,镜像体积太大,传输和部署都不方便。
选择基础镜像这里有些常用标准,可根据特定情况有所侧重:

稳定性 :你希望今天的构建能够为你提供与明天构建相同的基本库,目录结构和基础结构,否则你的应用程序将可能随时崩溃。
安全更新 :你希望基础映像得到良好维护,以便及时获得基本操作系统的安全更新。
最新的依赖关系
:除非你构建一个非常简单的应用程序,否则你可能依赖于操作系统安装的库和应用程序(例如编译器),希望他们版本不要太老。
广泛的依赖关系 :对于某些应用程序,可能需要不太流行的依赖关系 - 包含大量库的基本映像更适合该条原则。
最新的Python :虽然可以通过自己安装Python来解决这个问题,但拥有最新的Python可以节省你的工作量。
小镜像 :在所有条件相同的情况下,拥有较小的Docker镜像比使用更大的Docker镜像更好。

Python Docker镜像

Docker python基础镜像

FROM python:3.6

Alpine Linux ,最初是为小型设备设计的操作系统,因此往往有小包装。

FROM python:3.6-alpine

Debian Stretch
,安装了许多常见软件包。镜像本身很大,但理论上这些软件包是通过其他Docker镜像将使用的公共镜像层安装的,因此整体磁盘使用率会很低。

FROM python:3.6-stretch

Debian Stretch slim
版。这缺少了通用软件包的层,因此镜像本身要小得多,但如果你使用Stretch以外的许多其他Docker镜像,整体磁盘使用量会更高一些。

FROM python:3.6-slim-stretch

查看Python镜像大小,其中alpine 是最小的。

$ docker images | grep python
python  3.6-alpine          bb1ccaa5880c        4 days ago          86.7MB
python  3.6-stretch         32260605cf7a        7 days ago          929MB
python  3.6-slim-stretch   e0d20fa24f01        7 days ago          143MB
python  3.6                 ad01f54ca3a9        2 months ago        923MB

对于想要小镜像的人来说,一个常见的建议是使用Alpine Linux,但使用它会产生一些问题。首先,Alpine的库比我上面提到的其他Linux发行版少得多,因此你可能会缺少库。

Alpine和其他Linux发行版之间也存在重大差异:Alpine使用不同的C库,而不是更常见的glibc。 理论上,musl和glibc 大多是兼容的,但这些差异可能会导致奇怪的问题。

大多数这些问题已经得到解决,但可能发现更多问题。为了减少镜像体积,而导致可能发生的不确定性问题,这是不值得的。因此,这里建议不要使用Alpine。

那你应该怎么用?

直接使用 Debian Stretch 毫无意义,因为最新Python的基本映像就是基于此。

截至2019年6月:

python:3.6-slim-stretch 或者 python:3.6-stretch (或者你使用的任何Python版本而不是3.6)是一个比较好的基础镜像,slim变体版本可能会有更小的体积。
如果你需要比 Debian Stretch 提供的更新的库或编译器,你可能想要使用 ubuntu:18.04 ,它比 CentOS 更新。
一旦发布了 Debian Buster ,这个python镜像可能会有是一个更好的选择:它将预装新版本的Python和与 ubuntu:18.04 等效或更新的软件包。
当2020年4月到来时, ubuntu:20.04 将率先拥有最新的软件包

如何让 Docker 容器正常打印 Python 的日志

在 Docker 容器里跑 Python 程序时,我们经常遇到通过print函数或者logging模块输出的信息在容器 log 中迷之失踪,过了好久又迷之出现。这是因为 Python 在写 stdout 和 stderr 的时候有缓冲区,导致输出无法实时更新进容器 log。

有如下几种方法解决:

  1. 增加环境变量
    对于使用print函数打印的内容,在运行容器时增加环境变量PYTHONUNBUFFERED=0就可以解决。

  2. 配置 logging 的 stream 参数,stream与filename不能同时存在
    import logging
    logging.basicConfig(stream=sys.stdout)
    这样,通过 logging 模块打印的日志都会直接写到标准输出 stdout。

或者自定义两个StreamHandler分别配置为输出到 stdout 和 stderr,来对不同 log 分别进行输出处理。

  1. WSGI server 配置参数
    如果是以 WSGI server 运行的 web 应用,以 gunicorn 为例,在 gunicorn 的启动命令中增加参数–access-logfile - --error-logfile -即可。

以下链接的博文中介绍 了6种压缩Docker镜像的方法,可以参考
https://www.cnblogs.com/sevck/p/13608320.html

以下链接的博文中介绍 了Python Docker 最小化镜像:
https://www.jianshu.com/p/393b0b3ce82a

你可能感兴趣的:(Python,Linux,python,算法,docker)