Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建三步骤: 1. 编写dockerfile文件 2. docker build 3. docker run
在dockerhub网站上面以centos为例,查看其dockerfile的内容
FROM scratch
ADD centos-7-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="20200809" \
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-08-09 00:00:00+01:00"
CMD ["/bin/bash"]
Base镜像(scratch):Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
Dockerfile基础知识
Docker执行Dockerfile的大致流程
DockerFile 、Docker镜像、Docker容器的关系:
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
指令 | 作用 |
---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的 |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 容器构建时需要运行的命令 |
EXPOSE | 当前容器对外暴露出的端口 |
WORKDIR | 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点 |
ENV | ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样; |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 |
COPY | 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置 |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | 指定一个容器启动时要运行的命令 |
ENTRYPOINT | 指定一个容器启动时要运行的命令 |
ONBUILD | 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发 |
背景:使用从dockerhub上面拉取的镜像是没有vim 和ifconfig 命令的,这里我们自定义一个镜像,使得我们的centos镜像创建容器时候就自带这两个命令
构建DockerFile文件
[root@bigdata01 mydocker]# cd /mydocker/
[root@bigdata01 mydocker]# vi dockerfile2
FROM centos
MAINTAINER nice<[email protected]>
ENV mypath /usr/local
WORKDIR /tmp
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success----ok"
CMD /bin/bash
Build Dockerfile
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile2 -t nice/mycentos:1.3 .
Sending build context to Docker daemon 3.072kB
Step 1/10 : FROM centos
---> 831691599b88
Step 2/10 : MAINTAINER nice<[email protected]>
---> Running in 1bfae7ed3784
Removing intermediate container 1bfae7ed3784
---> 608ee480d3a5
Step 3/10 : ENV mypath /usr/local
---> Running in 5cde4bf46590
Removing intermediate container 5cde4bf46590
---> 3eaa07e83274
Step 4/10 : WORKDIR /tmp
---> Running in 924295eb2a3c
Removing intermediate container 924295eb2a3c
---> 33a0398d93d9
Step 5/10 : RUN yum -y install vim
---> Running in 623dedacee36
CentOS-8 - AppStream 669 kB/s | 5.8 MB 00:08
CentOS-8 - Base 329 kB/s | 2.2 MB 00:06
CentOS-8 - Extras 8.1 kB/s | 7.3 kB 00:00
Dependencies resolved.
、、、、、、
Total download size: 323 k
Installed size: 1.0 M
Downloading Packages:
net-tools-2.0-0.51.20160912git.el8.x86_64.rpm 1.4 MB/s | 323 kB 00:00
--------------------------------------------------------------------------------
Total 395 kB/s | 323 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Running scriptlet: net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Verifying : net-tools-2.0-0.51.20160912git.el8.x86_64 1/1
Installed:
net-tools-2.0-0.51.20160912git.el8.x86_64
Complete!
Removing intermediate container 41b956ae87fe
---> 1a38831365ae
Step 7/10 : EXPOSE 80
---> Running in a8c44ccb84fa
Removing intermediate container a8c44ccb84fa
---> 74743b39aa23
Step 8/10 : CMD echo $MYPATH
---> Running in 320eb480e5c8
Removing intermediate container 320eb480e5c8
---> 6528ca7b7306
Step 9/10 : CMD echo "success----ok"
---> Running in 9f6bdf0a76c5
Removing intermediate container 9f6bdf0a76c5
---> 58635bf5cf92
Step 10/10 : CMD /bin/bash
---> Running in 8fbcefef7924
Removing intermediate container 8fbcefef7924
---> b9e08611155a
Successfully built b9e08611155a
Successfully tagged nice/mycentos:1.3
[root@bigdata01 mydocker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nice/mycentos 1.3 b9e08611155a 30 seconds ago 295MB
run docker 容器
[root@bigdata01 mydocker]# docker run -it b9e08611155a
[root@d698b05d8ce9 tmp]# pwd
/tmp
以上可以知道,docker默认的工作目录是/tmp 目录,与我们设置的相同
使用docker history 命令查看镜像的构建历史
[root@bigdata01 mydocker]# docker history b9e08611155a
IMAGE CREATED CREATED BY SIZE COMMENT
b9e08611155a 3 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
58635bf5cf92 3 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
6528ca7b7306 3 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
74743b39aa23 3 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
1a38831365ae 3 minutes ago /bin/sh -c yum -y install net-tools 22.7MB
c02d91a59e73 3 minutes ago /bin/sh -c yum -y install vim 57.2MB
33a0398d93d9 3 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
3eaa07e83274 3 minutes ago /bin/sh -c #(nop) ENV mypath=/usr/local 0B
608ee480d3a5 3 minutes ago /bin/sh -c #(nop) MAINTAINER nice
831691599b88 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:84700c11fcc969ac0… 215MB
CMD和ENTRYPOINT的区别?
相同点:CMD和ENTRYPOINT都是指定一个容器启动时要运行的命令
不同点:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换,而ENTRYPOINT在docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合
案例需求:构造两个镜像,一个基于CMD指令,另一个基于ENTRYPOINT指令,分别测试两个指令的区别与联系
编写两个dockerfile
# CMD
FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "http://ip.cn" ]
# ENTRYPOINT
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
构建镜像:
# 构建CMD镜像
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile-centos-cmd -t nice/centos-cmd:1.0
"docker build" requires exactly 1 argument.
See 'docker build --help'.
age: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile-centos-cmd -t nice/centos-cmd:1.0 .
Sending build context to Docker daemon 5.12kB
Step 1/3 : FROM centos
---> 831691599b88
Step 2/3 : RUN yum install -y curl
---> Running in 9a15d717941c
CentOS-8 - AppStream 1.5 MB/s | 5.8 MB 00:03
CentOS-8 - Base 982 kB/s | 2.2 MB 00:02
CentOS-8 - Extras 4.1 kB/s | 7.3 kB 00:01
Package curl-7.61.1-12.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
Removing intermediate container 9a15d717941c
---> 0e16c491ea85
Step 3/3 : CMD [ "curl", "-s", "http://ip.cn" ]
---> Running in 86fd8a2acbce
Removing intermediate container 86fd8a2acbce
---> ad79bf05cf4b
Successfully built ad79bf05cf4b
Successfully tagged nice/centos-cmd:1.0
# 构建ENTRYPOINT镜像
[root@bigdata01 mydocker]# docker build -f /mydocker/dockerfile4 -t nice/centos-e:2.0 .
Sending build context to Docker daemon 5.12kB
Step 1/3 : FROM centos
---> 831691599b88
Step 2/3 : RUN yum install -y curl
---> Using cache
---> 0e16c491ea85
Step 3/3 : ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
---> Running in 7c33111bbca1
Removing intermediate container 7c33111bbca1
---> 553ff57039a7
Successfully built 553ff57039a7
Successfully tagged nice/centos-e:2.0
[root@bigdata01 mydocker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nice/centos-e 2.0 553ff57039a7 17 seconds ago 235MB
nice/centos-cmd 1.0 ad79bf05cf4b 11 minutes ago 235MB
nice/mycentos 1.3 b9e08611155a 2 hours ago 295MB
nice/centos latest 2da0623d0d63 2 weeks ago 215MB
nice/mytomcat latest f183c09f98b7 3 weeks ago 652MB
tomcat latest 2ae23eb477aa 4 weeks ago 647MB
nginx latest 08393e824c32 4 weeks ago 132MB
centos latest 831691599b88 2 months ago 215MB
hello-world latest bf756fb1ae65 8 months ago 13.3kB
进行测试:
[root@bigdata01 mydocker]# docker run -it ad79bf05cf4b -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.
[root@bigdata01 mydocker]# docker run -it 553ff57039a7 -i
HTTP/1.1 301 Moved Permanently
Date: Thu, 03 Sep 2020 09:59:11 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Thu, 03 Sep 2020 10:59:11 GMT
Location: https://ip.cn/
cf-request-id: 04f500fa8f0000930aa20c8200000001
Server: cloudflare
CF-RAY: 5cce9dd74c8a930a-SJC
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400
由以上可以看出使用CMD进行构建镜像的时候,在run容器的时候附加的命令会覆盖原来的CMD的命令,但是在使用ENTRYPOINT构建的进行,在run的时候附加的命令会追加到原来命令的后面组合成一个新的命令
目标:从centos构建一个tomcat镜像,安装JDK和tomcat ,配置共享目录,并使用案例进行测试
mkdir -p /mydocker/mytomcat
[root@bigdata01 mytomcat]# tree
.
├── apache-tomcat-8.5.34.tar.gz
├── c.txt
├── Dockerfile
├── jdk-8u221-linux-x64.tar.gz
└── test
│ ├── hello.jsp
│ └── WEB-INF
│ └── web.xml
└── tomcat-logs
Dockerfile 的内容如下:
FROM centos
MAINTAINER nice<[email protected]>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u221-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.34.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/localWORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_221
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.34
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.34
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-8.5.34/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-8.5.34/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-8.5.34/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.34/bin/logs/catalina.out
构建镜像
docker build -f /mydocker/mytomcat/Dockerfile -t nice/tomcat:1.0 .
启动容器
docker run -d -p 8888:8080 --name tomcat2 \
-v /mydocker/mytomcat/test:/usr/local/apache-tomcat-8.5.34/webapps/test \
-v /mydocker/mytomcat/tomcat-logs/:/usr/local/apache-tomcat-8.5.34/logs \
--privileged=true \
f29ace801e39
浏览器访问地址:http://192.168.52.50:8888/ 出现tomcat的猫图像
在test文件夹下面创建WEB-INF文件夹和hello.jsp,并且在WEB-INF里面创建web.xml 文件
hello.jsp 的内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
-----------welcome------------
<%="i am in docker tomcat self "%>
<br>
<br>
<% System.out.println("=============docker tomcat self");%>
</body>
</html>
web.xml 的内容如下:
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<display-name>testdisplay-name>
web-app>
创建之后重启容器,因为在本机的目录创建的文件,这里是和容器内的目录共享,所以重启容器之后即可访问测试
docker restart containerID