菜单

Juning
发布于 2020-05-27 / 1394 阅读
2
0

Docker(五) Dockerfile

Dockerfile简介

Dockerfile是用来构建docker镜像的文件,也就是一个命令参数脚本。

构建步骤:

  1. 编写一个Dockerfile文件
  2. docker build Dockerfile文件构建一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(dockerHub、阿里云仓库等地方)

首先我们看看centOS的官方Dockerfile是什么样子的:

dockerfile1.png

可以看到官方的镜像都是基础包,很多功能都没有,所以我们需要构建自己的镜像,比如我们需要一个Java的运行环境。

Dockerfile构建过程

  1. 在Dockerfile中有很多保留关键字(指令)都必须是大写的字母
  2. 执行是从上到下
  3. # 表示注释
  4. 每一个指令都会创建提交一个新的镜像层,并提交

dockerfile2.jpg

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镜像

  1. 准备镜像文件:Tomcat压缩包,JDK的压缩包
  2. 编写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
  1. 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
  1. 启动我们刚才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
  1. 访问测试
    image.png

  2. 发布项目(由于做了卷的挂载,我们直接在本地编写项目就可以发布了),在/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>

发现部署的项目成功,可以直接访问
image.png

也就是说,我们以后开发的都可以用docker镜像来发布

发布镜像

DockerHub

  1. 地址https://hub.docker.com需要自己注册账号
  2. 确认这个账号可以用
  3. 在服务器上提交自己的镜像
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
  1. 登录完成之后推送镜像
# 推送镜像的规范是: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

image.png
注:推送Docker Hub速度很慢,耐心等待,很有可能失败,失败会尝试多次重传,之后断开推送(但已推送上去的会保留,保留时间不知道是多久)。

一幅图总结(来自官方)

u=4261535913,3068120869fm=26gp=0.jpg.png

到这里其实使用docker已经没有问题了,写到这里,我看了一下,我的push已经完成了,这就是最后的效果:
image.png


评论