Docker如何制作镜像-Dockerfile的使用
1:什么是Dockerfile
Dockerfile是一个文本文档,可以通过docker build 命令构建成一个镜像。
我们可以在Dockerfile中定义一系列的命令,构建出我们想要的镜像。
想要制作一个新的镜像离不开Dockerfile。
2:Dockerfile 相关命令解释
只做比较重要的命令进行简单介绍,详情可看官网。
Dockerfile 官方文档:https://docs.docker.com/engine/reference/builder/#entrypoint
2.1:FROM
格式:
FROM [--platform=<platform>] <image> [AS <name>]
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
代表镜像来源,比如 FROM centos:7 就代表当前镜像的基础镜像为centos7。
若不需要基础镜像可以写成 FROM scratch
2.2:RUN
格式:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
也可以写成:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
\代表可换行拼接执行语句。
要使用除“/bin/sh”之外的不同 shell,请使用传入所需 shell的exec形式。例如:
RUN ["/bin/bash", "-c", "echo hello"]
docker 镜像在构建过程中将运行RUN 后面定义的命令。
2.3:CMD
格式:
FROM ubuntu
CMD echo "This is a test." | wc -
or
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
比如:
CMD netstat -ntpl 可以写成 CMD ["netstat","ntpl"]
CMD 命令在镜像构建期间并不会执行任何命令,而是指的镜像预期命令。
比如Dockerfile中的内容为:
FROM centos:7
CMD echo "hello docker"
进行docker build后不会报错,且执行docker run后也不会报错,因为 echo "hello word" 这条shell 命令在基础镜像 centos:7本身就是支持的。
但是Dockerfile中的内容若为:
FROM centos:7
CMD ["netstat","-ntpl"]
进行docker build后不会报错,且执行docker run后会报错,

因为 netstat -ntpl 这条shell 命令在基础镜像 centos:7中是不被支持的。
2.4:LABEL
镜像标签。一个镜像可以有多个标签。打标签时要在LABEL值中包含空格,请像在命令行解析中一样使用引号和反斜杠。
格式:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
可以通过 docker image inspect --format='' {镜像名称}:{镜像tag} 进行查看。
如:
FROM centos:7
LABEL version=2.0
CMD ["netstat","-ntp
运行后占用的端口模式80。

2.5:EXPOSE
格式:
EXPOSE 80/tcp
用以告知Docker 容器在运行时侦听指定的网络端口。可以指定端口是监听TCP还是UDP,如果不指定协议,默认为TCP。
但是无EXPOSE怎么设置,进行docker run -p port:port 命令时任然可以指定容器占用的端口。
如:
docker run -dit v3:3.0
运行后期望占用的端口为80(这么运行实际不会占用端口)。

但是若运行
docker run -dit -p 8081:8081 v3:3.0
那么容器运行后占用的端口为8081。

2.6:EVN
格式:
ENV <key>=<value>
简单来说就是为构建后的镜像定义环境变量(运行为容器后生效),如jdk版本、数据库连接配置等都可以设置。
2.7:ADD
格式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
该功能仅在用于构建 Linux 容器的 Dockerfile 上受支持,不适用于 Windows 容器。由于用户和组所有权概念不Linux和Windows,使用之间进行转换/etc/passwd,并/etc/group用于转换的用户和组名ID的限制此功能仅适用于基于Linux操作系统的容器是可行的。
ADD 命令即可添加本地的文件,也可以通过远程链接进行文件添加。
如果ADD的文件是本地tar文件,那么ADD到镜像后会自动解压缩。
2.8:COPY
格式:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
该功能仅在用于构建 Linux 容器的 Dockerfile 上受支持,不适用于 Windows 容器。由于用户和组所有权概念不Linux和Windows,使用之间进行转换/etc/passwd,并/etc/group用于转换的用户和组名ID的限制此功能仅适用于基于Linux操作系统的容器是可行的。
COPY 命令可将本地文件添加到镜像中,且无论何种文件都不会自动解压。
2.9:ENTRYPOINT
格式:
ENTRYPOINT ["executable", "param1", "param2"]
or
ENTRYPOINT command param1 param2
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。
如:
FROM centos:7
ENTRYPOINT echo "hello docker"
运行后效果为:

Dockerfile ENTRYPOINT、CMD、RUN的一些关系和区别。
2.10:VOLUME
格式:
VOLUME ["/data"]
作用运行镜像后再容器内部创建一个匿名数据卷,挂载在宿主机的文件系统下。
但是挂载的目录是随机默认的,无法指定在宿主机文件系统的具体哪个位置。
如:
FROM centos:7
VOLUME /application/dockerfile/volume
CMD ["/bin/bash"]
代表运行镜像后会在容器内部生成一个目录地址为 /application/dockerfile/volume 的数据卷。
通过docker volume ls 查看所有的数据卷。(再通过容器的启动时间和宿主机匿名文件夹创建的时间可以找到具体的文件夹位置)
再通过docker volume inspect {volume_name}可以看到挂载宿主机的哪个位置。

宿主机的这个位置下的文件是和容器中挂载的数据卷是互通的。宿主机新建、编辑、删除文件等操作会同步到容器中。
docker volume 详细官方文档为:https://docs.docker.com/storage/volumes/
博客文档为:
- https://www.cnblogs.com/edisonchou/p/docker_volumes_introduction.html
- https://blog.csdn.net/qq32933432/article/details/120944205
2.11:WORKDIR
格式:
WORKDIR /path/to/workdir
知名了WORKDIR 后 Dockerfile 中的 RUN、CMD、ENTRYPOINT、COPY和ADD 命令都将基于该文件夹下。
如:
FROM centos:7
WORKDIR /home
CMD ["/bin/bash"]
运行镜像后,进入容器的位置便是在/home位置下。
其他相关命令请参考官方文档。
3:如何构建一个新的镜像
3.1:如何从0-1构建一个镜像
1:我们先来看看centos官方是如何构建镜像的
github地址:https://github.com/CentOS/sig-cloud-instance-images/tree/CentOS-7.8.2003-x86_64/docker
结构图:

Dockerfile 中的内容为:
es (13 sloc) 523 Bytes
FROM scratch
ADD centos-7.8.2003-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20200504" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-05-04 00:00:00+01:00"
CMD ["/bin/bash"]
基础镜像也是需要一个二进制的文件的。如果你做过系统裁剪移植,那么很容易做出属于自己的体积更小的系统包(目前体积比较小的镜像有 busybox、alpine 等)。
docker 官方也提供了构建基础镜像的文章
2:开始尝试构建一个属于自己的基础镜像
我构建的基础镜像环境包括:
- centos7
- jdk8
- net-tools(网络工具)
Dockerfile内容:
# 空镜像
FROM scratch
# 添加官方给的二进制文件(会自动解压)
ADD centos-7.8.2003-x86_64-docker.tar.xz /
# 创建一个文件夹
RUN mkdir -p /application/jdk
# 将jdk8的
COPY jdk-8u261-linux-x64.tar.gz /application/jdk
# 安装net-tools 并删除jdk tar包以减少镜像的占用空间大小
RUN yum install net-tools -y && \
cd /application/jdk && \
tar -zxvf jdk-8u261-linux-x64.tar.gz && \
rm -rf jdk-8u261-linux-x64.tar.gz
# 设置jdk的环境变量
ENV JAVA_HOME=/application/jdk/jdk1.8.0_261
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
CMD ["/bin/bash"]
Dockerfile所处文件夹下需要有centos-7.8.2003-x86_64-docker.tar.xz、jdk-8u261-linux-x64.tar.gz 两个文件。
构建:
docker build -t centos7-jdk8:v1.0 .
运行:
docker run -dit --name centos7-jdk8 centos7-jdk8:v1.0
进入容器后运行java -version、netstat -ntpl 命令都可运行。

3.2:如何在基础镜像上构建一个镜像
经过上一个步骤后已经构建出了一个基础镜像了,然后我想把一个SpringBoot项目部署进去。
那么我应该如何写?
因为我的基础镜像已经有我要运行项目的所有环境了,因此我只需要把可执行的jar包丢进去运行即可。
Dockerfile内容:
# 基础镜像
FROM centos7-jdk8:v1.0
# 工作空间
WORKDIR /application/webapp
# 复制 jr包和启动脚本
COPY demo.jar .
COPY app.sh .
# 声明容器需要的端口号
EXPOSE 8022
# 赋予启动脚本可执行权限
RUN chmod a+x app.sh
# 容器启动后执行脚本启动
ENTRYPOINT ["./app.sh","start"]
Dockerfile文件夹下需要有demo.jar、app.sh 两个文件。
构建:
docker build -t demo:v1.0 .
运行:
# 因为jar包运行后占用端口为8022,因此需要宿主机和docker容器做一个端口映射
docker run -dit -p 8022:8022 --name dmeo demo:v1.0 /bin/bash
因为ENTRYPOINT命令在执行完命令后若没有一个前台进程执行,容器认为空闲,就会自行退出。
因此我在app.sh中特意添加了一句:

这样容器在启动后就不会自动退出了。
在宿主机执行curl -i 127.0.0.1:8022 '\w' 可以看到可以访问到请求404(说明服务启动了)。

4:镜像示意图

随着镜像的累积会导致镜像体积越来越大。
Docker如何制作镜像-Dockerfile的使用的更多相关文章
- docker commit 制作镜像
docker commit -m="commit jdk" --author="gutianlangyu" ae56f6cad215 gutianlangyu/ ...
- Docker 0x05: Dockerfile制作镜像
目录 Dockerfile制作镜像 一句话什么是dockerfile dockerfile脚本指令 小结 Dockerfile制作镜像 dockerfile 可以是制作自己镜像的脚本文件,按照这个脚本 ...
- 利用docker进行基础镜像制作
前言 最近想通过Javaee来开发博客,但是不想因为环境配置问题总是耗时间配置相关配置,所以萌生出用docker镜像来搭建web的系统环境,也是作为docker学习实践的笔记. docker hub注 ...
- centos7下安装docker(6镜像总结)
学了很长时间的镜像了,从镜像的分层,缓存的特性,到制作镜像:通过docker commint和docker build创建,再到制作dockerfile以及dockerfile中常用的参数FROM,M ...
- 记录 Docker 的学习过程 (dockerfile自动制作镜像)
自动制作镜像 通过编写dockerfile来自动创建镜像 #vi Dockerfile #编辑dockerfile文件,一定要以这个名字命名 #cat Dockerfile #导入哪个基础镜像FROM ...
- DOCKER学习_011:使用Dockerfile制作docker镜像
前面使用commit的方式,制作一个docker镜像,本次介绍使用Dockerfile制作一个dockers镜像 [root@docker-server3 ~]# mkdir /openssh [ro ...
- Docker --Dockerfile(制作镜像)
Dockerfile Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像 Dockerfile 常用指令 FROM 作用:指定基础镜像,Docke ...
- Docker系列06—基于容器制作镜像并上传到Docker Registry
本文收录在容器技术学习系列文章总目录 1.制作镜像 1.1 镜像的生成途径 基于容器制作 dockerfile,docker build 本篇主要详细讲解基于容器制作镜像:基于dockerfile 制 ...
- Docker笔记——jdk镜像制作
openjdk镜像依赖如下: openjdk:8-jdk -> buildpack-deps:jessie-scm -> buildpack-deps:jessie-curl -> ...
随机推荐
- Hadoop【MR开发规范、序列化】
Hadoop[MR开发规范.序列化] 目录 Hadoop[MR开发规范.序列化] 一.MapReduce编程规范 1.Mapper阶段 2.Reducer阶段 3.Driver阶段 二.WordCou ...
- 【原创】Altium生成Gerber时跳出The Film is too small for this PCB的解决办法
在用altium Designer画板子的时候,要生成gerber文件的时候,会出错,出现这样的提示框:"The Film is too small for this PCB" 原 ...
- Camera、音频录制与Vitamio框架
一.Camera 1.概述 Android框架包含了各种相机哥相机功能的支持,是你可以在应用中捕获图像和视频. 在应用能使用设备上的相机之前,先想一想将来会如何使用此硬件: (1)Camera 应该 ...
- maven内存溢出解决方法
maven内存溢出(InvocationTargetException: PermGen space) 解决方案:maven脚本:mvn.bat文件@REM set MAVEN_OPTS=-Xdebu ...
- SpringAOP浅析
1.问题 问题:想要添加日志记录.性能监控.安全监测 2.最初解决方案 2.1.最初解决方案 缺点:太多重复代码,且紧耦合 2.2.抽象类进行共性设计,子类进行个性设计,此处不讲解,缺点一荣俱荣,一损 ...
- 什么是javaScript闭包
闭包是与函数有着紧密的关系,它是函数的代码在运行过程中的一个动态环境,是一个运行期的概念. 所谓闭包,是指词法表示包括不必计算的变量的函数.也就是说,该函数能够使用函数外定义的变量. 在程序语言中,所 ...
- 3.使用Spring Data ElasticSearch操作ElasticSearch(5.6.8版本)
1.引入maven坐标 <!--spring-data-elasticsearch--><dependency> <groupId>org.springframew ...
- 【力扣】123. 买卖股票的最佳时机 III
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的 ...
- Anaconda+pycharm(jupyter lab)搭建环境
之前先是安装了pycharm,手动安装了python2.7和3.7版本,在pycharm里面使用alt+/手动下载包.后来想使用jupyter lab,手动下载包太麻烦且有版本管理的文艺,于是打算装A ...
- 接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket
引子 下一篇标题是<深入理解MQ生产端的底层通信过程>,建议文章读完之前.或者读完之后,再读一遍我之前写的<RabbitMQ设计原理解析>,结合理解一下. 我大学时流行过一个韩 ...