一、说明

学习docker有一段时间了,今天来做一个定制化的容器:centos+python+一些第三方python包,容器要复用的话需要形成镜像(一次定制n次使用)。在定制过程中也遇到了不少问题,现将其记录下来方便后续回看。好记心不如烂笔头!

需要用到的docker命令:
 docker pull
 docker run
 docker exec
 docker commit
 docker save
 docker load
 docker export
 docker import



二、定制容器

centos + python + 一些第三方python包

(一)启动基于centos镜像的容器

1. 从hub搜索镜像

执行docker search centos 发现列表没有tag(版本号),而且很多都是非官方的镜像。 OFFICIAL 列的值为 [OK] 的才是官方镜像。

docker怎么镜像生成容器 docker容器制作镜像_docker怎么镜像生成容器

要找具体版本只能去 dockerhub 上找 : https://hub.docker.com/u/library

输入 centos 进行搜索:

docker怎么镜像生成容器 docker容器制作镜像_docker基于容器制作镜像_02

从官方centos容器链接进去

点击“Tags”标签页可以看到容器的所有版本列表:

docker怎么镜像生成容器 docker容器制作镜像_docker定制镜像_03


注意

:“latest”并不是真正意义上的最新版本,其实“latest”就像“1.0”、“2.0”等一样也只是一个普通tag而已,估计官方在下一次发布新版本的时候又会将最新镜像标记为“latest”,所以你永远不知道“latest”到底是哪个版本,docker安装镜像在不指定版本号时默认使用的是“latest”镜像(理解为当时的最新版,后续有版本更新时docker并不会自动将该镜像更新到最新版)。

2. 拉取镜像

我们找到centos7,进行安装,点击傍边的按钮,复制pull命令,开始执行:

#拉取centos7镜像
docker pull centos:centos7

#查询镜像,找到 IMAGE_ID ,比如:b5b4d78bc90c    
docker images

3. 启动容器

通过镜像ID启动容器

#先建立目录,用于映射docker容器的工作目录。
mkdir /opt/docker/container_data  

#通过镜像id启动容器,并指定工作目录,以及工作目录和宿主机器目录的映射关系
docker run -v /opt/docker/container_data:/data  -w /data --name centos7 -itd b5b4d78bc90c /bin/bash 

#当然你也可以通过镜像名+tag来启动 
docker run -v /opt/docker/container_data:/data  -w /data --name centos7 -itd centos:centos7 /bin/bash 

#查看容器启动情况  
docker ps -a


(二)在centos容器中安装python

docker怎么镜像生成容器 docker容器制作镜像_python_04


进入centos7容器:

#通过容器名进入容器,上面在 docker run 的时候指定了容器名为centos7
docker exec -it centos7 bash

docker怎么镜像生成容器 docker容器制作镜像_python_05

1.安装python3.7

通过编译源码的方式安装python3.7

#安装编译需要的依赖包
yum install bzip2-devel sqlite-devel zlib-devel ncurses-devel readline-devel tk-devel openssl-devel gcc make
yum install libffi-devel -y

#下载python3.7源码 
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz

#在当前目录解压源码
tar -zxvf Python-3.7.0.tgz 

#进入解压目录 
cd Python-3.7.0

#编译配置:将需要编译的源码进行配置,检查当前的环境是否满足要安装软件的依赖关系 
./configure

#编译源码
make

#安装
make install

#安装完之后,查看python3是否安装成功,如果安装成功则会显示版本号。
python3 --version 

#安装成功之后可以删除源码,这样可以减少镜像的体积      
cd .. 
rm Python-3.7.0.tgz
rm -rf Python-3.7.0/



2.建立python软链接


先看看 /usr/bin 目录下有没有python :

ls -lt /usr/bin | grep python

docker怎么镜像生成容器 docker容器制作镜像_docker怎么镜像生成容器_06


我们发现centos7自带python2.7 ,而且python的软链接指向python2.7,

于是我们删除该软链接,重新建一个软链接指向python3:

#找到python3所在路径: /usr/local/bin/python3
where is python3

#删除python2的软连接
rm /usr/bin/python 

#添加python3的软连接
ln -s /usr/local/bin/python3 /usr/bin/python

/usr/bin/pip 软链接也按照上面的方法,链接到pip3 ,否则你执行pip也是跑的pip2。

注意: 由于yum命令依赖python2.7,因此需要修改几处地方:
把如下两个文件中的第一行 #! /usr/bin/python 改为 #! /usr/bin/python2.7 ,然后保存即可。

vi /usr/libexec/urlgrabber-ext-down
vi /usr/bin/yum



3. 安装自己需要的第三方python包

  1. 修改pip仓库地址为国内镜像,这样可以增加下载速度
    修改 ~/.pip/pip.conf 文件, 没有该文件则创建一个,如使用阿里云的镜像
[global]
timeout = 6000
index-url = http://mirrors.aliyun.com/pypi/simple/
trusted-host = mirrors.aliyun.com
  1. 安装软件包
    比如我想用到如下三个python包:
pip install wordcloud
pip install matplotlib
pip install turtule


三、制作镜像

1. 找到容器名(或容器id): centos7

docker container ls

docker怎么镜像生成容器 docker容器制作镜像_docker_07

2. 提交镜像到本地:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

#将容器提交为一个镜像  
docker commit -m "基于centos7的Pytho3.7镜像" centos7 centos7_python37:1.0
#或者也可以不写提交备注:
docker commit c7 centos7_python37:1.0

docker怎么镜像生成容器 docker容器制作镜像_docker怎么镜像生成容器_08


然后执行 “docker images” 发现本地多了一个镜像: (注意 IMAGE ID 为镜像sha256的前12位)

docker怎么镜像生成容器 docker容器制作镜像_docker基于容器制作镜像_09


到这一步镜像就制作完成了。

3. 镜像的导出/导入

docker save 导出

#保存镜像: docker save -o <保存路径> <镜像名称:标签> 
docker save -o ./centos7_python37_v1.0.tar centos7_python37:1.0

docker load 导入,可以将镜像文件 centos7_python37_v1.0.tar 拷贝到另一台机器,进行导入:

#加载镜像:docker load --input <镜像路径>
docker load --input ./centos7_python3.7_v1.0.tar



4.容器的导入导出

当然你也可以不commit,不生成镜像,直接export导出容器,然后在其他机器通过import导入来使用

#导出容器: docker export <容器名> > <容器tar保存路径>
docker export centos7 > ./centos7_python37_v1.0.tar
#导入容器,导出的是一个容器,但是导入后成为一个镜像: docker import <容器tar文件路径> <镜像名:tag> 
docker import ./centos7_python37_v1.0.tar centos7_python37:1.0

注意:导出的是一个容器的tar文件,但是将tar文件导入后将成为一个镜像,docker import 后可以通过 docker images 看到导入后生成的镜像



5. save/load 与 export/import 的区别

save/load:
通过 docker save 将一个镜像导出为tar文件,由于 docker save 会保存该镜像的的所有历史记录,所以文件体积比 docker export 导出的大。
再使用 docker load 将tar文件导入成为一个本地镜像。

export/import:
通过 docker export 将一个容器导出为tar文件,不需要commit形成镜像,而是直接导出容器,相比 docker save 命令,容器tar文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
再使用 docker import 将tar文件导入成为一个新的镜像(而不是容器)。

可以通过 docker history 查看镜像的操作历史
docker history centos7_python37:1.0

docker怎么镜像生成容器 docker容器制作镜像_docker怎么镜像生成容器_10