每次使用的docker镜像都是基于它人制作好的镜像,如何想要自己定制一个镜像。
在虚拟机中安装好系统,然后进入该系统中将某些目录的文件打成tar包,再通过docker的import命令来创建镜像
打包时其中/proc、/sys、/run、/dev这几个目录都是系统启动时自动生成的,虽然也属于文件系统一部分,但是他们每次开机都会有变化,所以打包的时候就应该忽略它们。
tar -cvpf /tmp/base_system.tar --directory=/ --exclude=proc --exclude=sys --exclude=dev --exclude=run --exclude=boot
需要注意的是,在打包之前,请先确认要将哪些文件进行打包,比如下面这些目录都可以不用打包:
某些用户的home目录是否需要打包 每个用户的执行的历史命令是否需要清除 一些涉及到隐私的文件 与系统镜像没有关系的文件,或者说只是系统运行过程中保存的垃圾文件或者缓存等 临时文件 建议手动选择要进行打包的目录,比如:bin dev lib64 media opt root snap var boot etc lib mnt sbin srv usr vmlinuz这些目录 如果你拿不准哪些文件目录要打包,那么可以将根目录下所有文件都打包(不推荐)
cd /
tar -cf base_system.tar bin dev lib64 media opt root snap var boot etc lib mnt sbin srv usr vmlinuz
打包部分目录
tar -cf base_system.tar bin etc home lib lib64 media mnt opt root sbin srv usr var
cat base_system.tar | docker import - ubuntu:18.04
dockerfile 中 复制当前目录下的目录到指定目录下并保持目录名不变
在 Dockerfile 中,你可以使用 COPY 指令将当前目录下的目录复制到指定的目录,并保持目录名称不变。例如,假设你希望将当前目录下的 myfolder 复制到 Docker 镜像的 /app 目录下,你可以使用以下的 Dockerfile 指令:
COPY myfolder /app/myfolder
这将会创建一个新的目录 /app/myfolder 并且将 myfolder 目录的所有文件复制到这个新目录。
如果你希望复制当前目录下的所有文件和目录到镜像的 /app 目录,你可以使用以下的 Dockerfile 指令:
基于CentOS 7镜像增加支持中文、调整时区
yum install -y kde-l10n-Chinese安装中文包 localedef -c -f UTF-8 -i zh_CN zh_CN.utf8安装完中文包后应用 ENV LC_ALL "zh_CN.UTF-8"配置环境变量 ENV TZ Asia/Shanghai配置时区
基于Alpine 镜像构建时调整时区
在k8s编排文件中配置
有时出于安全、精简考虑需要基于CentOS系统的纯净基础镜像构建应用的镜像,可以参考CentOS官方在GitHub上的这个项目
选择想要系统版本的分支,检出代码进行构建 下面以CentOS7最新版(7.9.2009版本)为例
下面是Dockerfile内容,可以在该文件的基础上再添加自己需要的软件
Dockerfile中ENTRYPOINT和CMD的用法
简单的区别就是ENTRYPOINT执行的内容在容器启动时不会被指定的命令覆盖,而CMD则会 示例:
根据上面的Dockerfile构建镜像,不带参数启动容器时,会执行ping -c 3 localhost。 但如果我想用这个容器来ping另外一个地址时就不用重新构建,只需要在docker run的时候加上新地址即可
上面的命令运行的容器就会执行ping -c 3 <www.baidu.com>,Dockerfile中CMD定义的localhost就被替换成了www.baidu.com但ENTRYPOINT定义的内容则不会被修改
另外,ENTRYPOIN、CMD和RUN运行命令都支持两种写法分别是shell和exec
Shell形式的ENTRYPOINT忽略任何CMD或docker运行命令行参数 shell写法示例:
ENTRYPOINT的Exec形式允许您设置命令和参数,然后使用任一形式的CMD来设置更可能更改的其他参数。使用ENTRYPOINT参数,而可以通过Docker容器运行时提供的命令行参数覆盖CMD。 exec写法示例:
注意:ENTRYPOINT 和 CMD 不能同时为字符串值。 它们可以都是列表,或者 ENTRYPOINT 为一个列表而 CMD 为一个字符串值;但如果 ENTRYPOINT 为一个字符串值,则 CMD 将被忽略。这是将参数字符串转换为列表后无法避免的不幸后果。
如果说今天您可以学到一个经验 ,那就是要遵循以下一般原则:
ENTRYPOINT + CMD = 默认容器命令参数
ENTRYPOINT 也可覆盖
假设我们拥有如下的 Dockerfile,并从它创建了一个叫做 myservice 的映像:
通过运行如下命令来修改 ENTRYPOINT:
同时覆盖 ENTRYPOINT 和 CMD
我们能否同时覆盖 ENTRYPOINT 和 CMD? 当然可以:
Dockerfile
start.sh
start.sh