Dockerfile简介
Dockerfile是用来构建docker镜像的文件,也就是一个命令参数脚本。
构建步骤:
- 编写一个Dockerfile文件
- docker build Dockerfile文件构建一个镜像
- docker run 运行镜像
- docker push 发布镜像(dockerHub、阿里云仓库等地方)
首先我们看看centOS的官方Dockerfile是什么样子的:
可以看到官方的镜像都是基础包,很多功能都没有,所以我们需要构建自己的镜像,比如我们需要一个Java的运行环境。
Dockerfile构建过程
- 在Dockerfile中有很多保留关键字(指令)都必须是大写的字母
- 执行是从上到下
- # 表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
Dockerfile是面向开发的,我们以后要发布项目就需要制作镜像,就需要编写Dockerfile文件,这个文件也非常简单
Dockerfile镜像逐渐成为企业交付的标准,所以我们必须得掌握
整个流程为开发、部署、运维。。。缺一不可,下面是大致的步骤:
-
Dockerfile:构建文件,定义可以切的步骤,源代码
-
dockerimages:通过Dockerfile构建生成的镜像,最终发布和运行的产品
-
docker容器:容器是镜像运行起来提供服务
Dockerfile的指令
以前我们都是使用别人的,现在我们知道了这些命令之后,我们就可以尝试着写一个自己的Dockerfile(不止下面这么多,但下面的都是常用的)
命令 | 注释 |
---|---|
FROM | 基础镜像,一切从这里开始构建 |
MAINTAINER | 维护者信息,表示镜像是谁写的,一般都是姓名+邮箱 |
RUN | 镜像构建时需要运行的命令 |
ADD | 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载到目录位置 |
EXPOSE | 暴露端口,与-p相似 |
CMD | 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被代替 |
ENTRYPOINT | 指定这个容器启动的时候要执行的命令,可以追加命令 |
ONBUILD | 设置自径想的编译钩子指令从该镜像生成子镜像,在子镜像的编译过程中,首先会执行父镜像中的ONBUILD指令,所有编译指令都可以成为钩子指令 |
COPY | 复制文件到镜像中,类似于ADD |
ENV | 设置容器的环境变量 |
实战测试
官方提供的centOS里面缺失了很多常用的命令,比如vim,现在我们就创建一个属于我们自己的centOS
创建一个Dockerfile文件:
# 镜像基于centOS
FROM centos
# 作者信息
MAINTAINER juning<juning0908@qq.com>
# 设置一个环境变量
ENV MYPATH /user/juning
# 将工作目录设置为刚才设置的环境变量的地址
WORKDIR $MYPATH
# 安装vim
RUN yum -y install vim
# 安装 net-tools
RUN yum -y install net-tools
# 输出环境变量(工作目录的地址)
CMD echo $MYPATH
# 输出一个end
CMD echo "----end----"
# 进入/bin/bash目录
CMD /bin/bash
通过刚刚创建的Dockerfile构建镜像,注意最后面有一个空格和点
docker build -f Dockerfile -t juning_centos:0.1 .
查看并测试运行:
juning@chengjiajundeMacBook-Pro docker_app_data % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
juning_centos 0.1 23e4981a4426 About a minute ago 321MB
juning@chengjiajundeMacBook-Pro docker_app_data % docker run -it juning_centos:0.1
[root@cabc4cc9be09 juning]# pwd
/user/juning
[root@cabc4cc9be09 juning]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 13 bytes 1046 (1.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@cabc4cc9be09 juning]# touch a.txt
[root@cabc4cc9be09 juning]# vim a.txt
[root@cabc4cc9be09 juning]#
可以看到我们设置的工作目录是/user/juning,我们安装的软件也都有了
到这里,我们创建的第一个Dockerfile文件成功完成
在这里再补充一个命令来查看当前镜像是怎么一步一步做起来的:
juning@chengjiajundeMacBook-Pro ~ % docker history juning_centos:0.1
IMAGE CREATED CREATED BY SIZE COMMENT
23e4981a4426 10 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
88dced0d44ff 10 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
1629e183e024 10 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
0078e1efcf2f 10 minutes ago /bin/sh -c yum -y install net-tools 24.1MB
fe669d53fc01 10 minutes ago /bin/sh -c yum -y install vim 59.8MB
34d496082637 12 minutes ago /bin/sh -c #(nop) WORKDIR /user/juning 0B
a1936f5b0743 12 minutes ago /bin/sh -c #(nop) ENV MYPATH=/user/juning 0B
8b3d9ce62c47 12 minutes ago /bin/sh -c #(nop) MAINTAINER juning<juning0… 0B
470671670cac 4 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 4 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 4 months ago /bin/sh -c #(nop) ADD file:aa54047c80ba30064… 237MB
通过这个命令,我们平时拿到一个镜像,就可以研究一下别人的镜像是怎么做的了
CMD和ENTRYPOINT的区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被代替
ENTRYPOINT # 指定这个容器启动的时候要执行的命令,可以追加命令
测试CMD
# 编写Dockerfile文件
juning@chengjiajundeMacBook-Pro docker_test % vi dockerfile-cmd-test
FROM centos
CMD ["ls", "-a"]
# 构建镜像
juning@chengjiajundeMacBook-Pro docker_test % docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM centos
---> 470671670cac
Step 2/2 : CMD ["ls", "-a"]
---> Running in 1b4fd4b18f78
Removing intermediate container 1b4fd4b18f78
---> 3857fc168157
Successfully built 3857fc168157
Successfully tagged cmdtest:latest
# 运行镜像,发现我们的ls -a命令生效了
juning@chengjiajundeMacBook-Pro docker_test % docker run cmdtest:latest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 然后我们想在后面追加一个命令 -l 让命令变成 ls -al会发现如下报错
juning@chengjiajundeMacBook-Pro docker_test % docker run cmdtest:latest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled
# cmd的情况下 -l替换了 CMD ["ls", "-a"],而-l并不是一个命令,所以报错
测试ENTRYPOINT
# 创建dockerfile文件
juning@chengjiajundeMacBook-Pro docker_test % vi dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls", "-a"]
# 编译
juning@chengjiajundeMacBook-Pro docker_test % docker build -f dockerfile-entrypoint-test -t entrypointtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 470671670cac
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Running in 3eaa3aa63a4b
Removing intermediate container 3eaa3aa63a4b
---> f6c77775a682
Successfully built f6c77775a682
Successfully tagged entrypointtest:latest
# 运行镜像,并加上参数,可以看见 ls -al 效果正常
juning@chengjiajundeMacBook-Pro docker_test % docker run entrypointtest:latest -l
total 56
drwxr-xr-x 1 root root 4096 May 28 12:39 .
drwxr-xr-x 1 root root 4096 May 28 12:39 ..
-rwxr-xr-x 1 root root 0 May 28 12:39 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 28 12:39 dev
drwxr-xr-x 1 root root 4096 May 28 12:39 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64
drwx------ 2 root root 4096 Jan 13 21:48 lost+found
drwxr-xr-x 2 root root 4096 May 11 2019 media
drwxr-xr-x 2 root root 4096 May 11 2019 mnt
drwxr-xr-x 2 root root 4096 May 11 2019 opt
dr-xr-xr-x 161 root root 0 May 28 12:39 proc
dr-xr-x--- 2 root root 4096 Jan 13 21:49 root
drwxr-xr-x 11 root root 4096 Jan 13 21:49 run
lrwxrwxrwx 1 root root 8 May 11 2019 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 May 11 2019 srv
dr-xr-xr-x 12 root root 0 May 26 14:58 sys
drwxrwxrwt 7 root root 4096 Jan 13 21:49 tmp
drwxr-xr-x 12 root root 4096 Jan 13 21:49 usr
drwxr-xr-x 20 root root 4096 Jan 13 21:49 var
也就是说,ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。
实战:Tomcat镜像
- 准备镜像文件:Tomcat压缩包,JDK的压缩包
- 编写Dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,不需要 -f 指定了
FROM centos
MAINTAINER juning<juning0908@qq.com>
# 使用ADD命令会自动解压
ADD jdk-8u201-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.35.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_201
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.35
ENV PATH $PATH:$JAVA_HOME/lib:$CATALINA_HOME/bin:$CATALINA_HOME/lib
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out
- build dockerfile
juning@chengjiajundeMacBook-Pro docker_test % docker build -t diy_tomcat .
Sending build context to Docker daemon 203MB
Step 1/14 : FROM centos
---> 470671670cac
Step 2/14 : MAINTAINER juning<juning0908@qq.com>
---> Using cache
---> 8b3d9ce62c47
Step 3/14 : ADD jdk-8u201-linux-x64.tar.gz /usr/local/
---> Using cache
---> 089e17cd22da
Step 4/14 : ADD apache-tomcat-9.0.35.tar.gz /usr/local/
---> Using cache
---> 8fd06bc19ad5
Step 5/14 : RUN yum -y install vim
---> Using cache
---> 7b795fac3ae1
Step 6/14 : ENV MYPATH /usr/local
---> Using cache
---> ee979e03f7dc
Step 7/14 : WORKDIR $MYPATH
---> Using cache
---> b93c7dd07fcc
Step 8/14 : ENV JAVA_HOME /usr/local/jdk1.8.0_201
---> Using cache
---> 7e05d9c4fed9
Step 9/14 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
---> Using cache
---> 294ac9791fb6
Step 10/14 : ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35
---> Using cache
---> 6d196a7795e2
Step 11/14 : ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.35
---> Using cache
---> 8781cd755533
Step 12/14 : ENV PATH $PATH:$JAVA_HOME/lib:$CATALINA_HOME/bin:$CATALINA_HOME/lib
---> Using cache
---> 97cebd661aca
Step 13/14 : EXPOSE 8080
---> Using cache
---> 730a09049b01
Step 14/14 : CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out
---> Running in 1ab1515970af
Removing intermediate container 1ab1515970af
---> d7927f06678a
Successfully built d7927f06678a
Successfully tagged diy_tomcat:latest
- 启动我们刚才build的镜像
docker run -d -p 9090:8080 --name test_diy_tomcat2 -v /Users/juning/dev/docker_app_data/docker_test/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /Users/juning/dev/docker_app_data/docker_test/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.35/logs diy_tomcat
-
访问测试
-
发布项目(由于做了卷的挂载,我们直接在本地编写项目就可以发布了),在/Users/juning/dev/docker_app_data/docker_test/tomcat/test目录下创建index.jsp文件,在/Users/juning/dev/docker_app_data/docker_test/tomcat/test/WEB-INF目录下创建web.xml文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>你好docker</title>
</head>
<body>
Hello World!<br/>
<%
System.err.println("我是docker部署的页面");
%>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
发现部署的项目成功,可以直接访问
也就是说,我们以后开发的都可以用docker镜像来发布
发布镜像
DockerHub
- 地址https://hub.docker.com需要自己注册账号
- 确认这个账号可以用
- 在服务器上提交自己的镜像
juning@chengjiajundeMacBook-Pro docker_test % docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
登录命令如下:
docker login -u yourUserName -p yourPWD
- 登录完成之后推送镜像
# 推送镜像的规范是:docker push 注册用户名/镜像名
# tag命令修改为规范的镜像
docker tag diy_tomcat juning/diy_tomcat
# 查看修改后的规范镜像:
juning@chengjiajundeMacBook-Pro docker_test % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diy_tomcat latest d7927f06678a About an hour ago 709MB
juning/diy_tomcat latest d7927f06678a About an hour ago 709MB
# 通过push命令推送镜像:
docker push juning/diy_tomcat
注:推送Docker Hub速度很慢,耐心等待,很有可能失败,失败会尝试多次重传,之后断开推送(但已推送上去的会保留,保留时间不知道是多久)。
一幅图总结(来自官方)
到这里其实使用docker已经没有问题了,写到这里,我看了一下,我的push已经完成了,这就是最后的效果: