docker build

Docker 构建镜像


一、Dockerfile

  • Dockerfile指令

1. 常用指令

# 定义了使用指定基础镜像作为启动构建流程。
FROM '镜像名称[:TAG]'
# 声明镜像维护者信息。
MAINTAINER '[用户信息]'

# 设置环境变量(可以写多条)。
ENV '[key]' '[value]'
# 构建容器时需要运行的命令(可以写多条)。
RUN '[命令command]'
# 设置终端默认登录进来的工作目录。
WORKDIR '[path_dir]'
# 当前容器对外暴露出的端口。
EXPOSE '[端口port]'

# 将宿主机的文件复制到容器内(如果是一个压缩文件,将会在复制后自动解压)。
ADD 'source_dir/file' 'dest_dir/file'
# 和`ADD`相似(但是如果有压缩文件是不能解压)。
COPY 'source_dir/file' 'dest_dir/file'

# 创建一个可以从本地主机或其他容器挂载的挂载点(一般用来存放数据库和需要保持的数据等)。
VOLUME

# 指定容器启动时要运行的命令(假如有多个CMD,最后一个生效)。
CMD
# 指定容器启动时要运行的命令。
ENTRYPOINT

# 为子镜像服务,当构建一个被继承的`Dockerfile`时运行的命令。
# 父镜像在被子镜像继承后,父镜像的[ONBUILD]被触发(理解为触发器)。
ONBUILD

2. CMD 和 ENTRYPOINT 的区别和联系

  • CMD 和 ENTRYPOINT 都是容器启动的时候,要执行的命令。
  • 都支持 exec 和 shell 方式。
  1. 一般用法是,单独一个 CMD。
  2. 或者先 ENTRYPOINT,后跟 CMD 结合使用。

  • 假如有多个 CMD,启动的时候带命令参数,会覆盖前面配置的 CMD命令,最后一个命令参数生效。
  • 所以平时用 CMD 的时候,就是单独一个 CMD命令 即可,启动命令也不带参数。

2.1 Tomcat 示例

# 第一种
# 1、看下`Tomcat官方镜像的Dockerfile`。
CMD ["catalina.sh","run"]
# 2、由于`CMD命令`有多个,会被覆盖,只有最后一个执行。

# 3. 启动不带参数,tomcat可以正常启动。
docker run -it --name=tomcat8_1 -p 8080:8080 镜像ID	

# 4. 如果加上参数,比如`/bin/bash`或者`ls -l`,就会覆盖Dockerfile中的CMD ["catalina.sh","run"]
docker run -it --name=tomcat8_2 -p 8081:8080 镜像ID	ls -l	
# tomcat就不执行,执行的是具体启动时候带的参数

2.2 Redis 示例

# 第二种
# 1. 看下redis的官方镜像的Dockerfile
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["redis-server"]
# 2. 先ENTRYPOINT执行下命令,然后跟CMD来拼接具体的执行参数;最终执行的是 `docker-entrypoint.sh redis-server`

2.3 CMD 语法

# 1. 运行一个可执行的文件并提供参数
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
# 2. 为ENTRYPOINT指定参数
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
# 3. 是以`/bin/sh -c`的方法执行的命令(shell form)
CMD command param1 param2 (shell form)

2.4 ENTRYPOINT 语法

ENTRYPOINT ["executable", "param1", "param2"] (exec 格式【官方推荐】)
ENTRYPOINT command param1 param2 (shell 格式)

2.5 CMD 测试

FROM centos
CMD echo "abc"
# CMD ["/bin/echo", "defg"]
  1. 可以测试运行,看看结果;
  2. 以及把第二个CMD去掉,看看结果;
  3. 以及运行命令后面跟运行参数,看看结果;能明白CMD多个的话,只有最后一个生效。

2.6 CMD 结合 ENTRYPOINT 测试

FROM centos
ENTRYPOINT ["ls"]
CMD ["-l"]
  1. 我们用ENTRYPOINT执行一个ls命令,然后CMD追加参数,相当于这个CMD是默认的一个参数 ls -l;
  2. 假如需要更换参数,启动的时候 ,我们直接替换即可;

3. ONBUILD 详解

  1. 当构建一个被继承的 Dockerfile 时运行的命令,父镜像在被子镜像继承后父镜像的 ONBUILD 被触发; 可以把 ONBUID 理解为一个触发器;
  2. 其他命令都是为了自身镜像服务的,只有 ONBUILD 是为了子镜像服务;
# 父镜像Dockerfile
FROM centos
ONBUILD RUN yum -y install vim
CMD /bin/bash

# 子镜像Dockerfile
FROM parent
# 父镜像名

  1. 当构建子镜像的时候,父镜像的ONBUILD会触发,子镜像直接安装vim;
  2. 实际应用,一般是ONBUILD里执行的是一些父镜像暂时无法执行的东西,比如一些COPY、ADD,可以启动一些服务,父镜像当做模板,仅仅提供基础支持,然后具体实行是子镜像操作。

4. VOLUME 实现容器卷

# 容器home目录下创建[v1, v2]目录
VOLUME['/home/v1','/home/v2']

说明:前面用启动命令 -v 宿主机目录:容器卷目录来实现容器卷目录挂载,但是由于定义Dockerfile的时候,并不能保证在所有的宿主机上都有这样的特定目录,所以在Dockerfile定义中,只能指定容器卷目录


4.1 编写 Dockerfile

# 1. 创建`Dockerfile`文件
# touch /root/docker/Dockerfile

# VOLUME
FROM centos
VOLUME ["/home/v1","/home/v2"]
CMD /bin/bash

4.2 构建镜像

# 构建 
docker build -t test:2020-latest /root/docker/

4.3 测试运行镜像

# 运行 
docker run -it --name=test_1 镜像ID

# 运行后,我们进入home目录,找到[v1, v2]两个容器卷目录
cd /home
ls -l	# 看到[v1, v2]两个容器卷目录

# 退出容器不停止
Ctrl+P+Q 

# 然后我们通过下面命令,来查看下默认生成的 容器卷目录 对应的 宿主机目录
docker inspect 容器ID
# 宿主机目录("Source": "/var/lib/docker/volumes/.../_data")
# 容器卷目录("Destination": "/home/v1")
"Mounts": [
    {
        "Type": "volume",
        "Name": "b9b3f2af876fea97a31f23bd3ff7255b412da4c83774ddeda777e690901d2183",
        "Source": "/var/lib/docker/volumes/b9b3f2af876fea97a31f23bd3ff7255b412da4c83774ddeda777e690901d2183/_data",
        "Destination": "/home/v1",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    },
    {
        "Type": "volume",
        "Name": "afabba99c9945138734b092ffcb8cf270f0ceabb2b784f4cbbacf9e845bab376",
        "Source": "/var/lib/docker/volumes/afabba99c9945138734b092ffcb8cf270f0ceabb2b784f4cbbacf9e845bab376/_data",
        "Destination": "/home/v2",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

二、常用软件


1. CentOS


1.1 编写 Dockerfile

# 1. 创建`Dockerfile`文件
# touch /root/docker/Dockerfile

# centos-8
FROM centos
MAINTAINER qs<443749091@qq.com>

LABEL name="centos-8 Image" \
build-date="20200715"

ENV WORKPATH /home/
WORKDIR $WORKPATH

RUN yum -y install net-tools
RUN yum -y install vim

EXPOSE 80
CMD /bin/bash

1.2 构建镜像

# 构建
docker build -t centos-8:2020-latest /root/docker/
-t				# 给镜像加一个TAG
/root/docker/	# Dockerfile目录

1.3 测试运行镜像

# 运行
docker run -it --name=centos_1 镜像ID

1.4 查看镜像历史

# 查看镜像历史
docker history 镜像ID

2. Tomcat


2.1 编写 Dockerfile

# 1. 创建`Dockerfile`文件
# touch /root/docker/Dockerfile

# tomcat-8
FROM centos
MAINTAINER qs<443749091@qq.com>

LABEL name="tomcat-8 Image" \ 
build-date="20200715"

COPY copyright.txt /home/copyright.txt
ADD server-jre-8u151-linux-x64.tar.gz /home/
ADD apache-tomcat-8.5.37.tar.gz /home/

ENV WORKPATH /home/apache-tomcat-8.5.37/
WORKDIR $WORKPATH

ENV JAVA_HOME /home/jdk1.8.0_151
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /home/apache-tomcat-8.5.37/
ENV CATALINA_BASE /home/apache-tomcat-8.5.37/
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080
CMD ["/home/apache-tomcat-8.5.37/bin/catalina.sh","run"]

2.2 构建镜像

# 构建 
docker build -t tomcat-8:2020-latest /root/docker/

2.3 测试运行镜像

# 运行 
docker run -it --name=tomcat_1 -p 8080:8080 镜像ID

3. MyCat


3.1 编写 Dockerfile

# 1. 创建`Dockerfile`文件
# touch /root/docker/Dockerfile

# mycat
FROM centos
MAINTAINER qs<443749091@qq.com>

LABEL name="mycat Image" \
build-date="20200715"

ADD server-jre-8u151-linux-x64.tar.gz /home/
ADD Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz /home/

ENV WORKPATH /home/mycat/
WORKDIR $WORKPATH

ENV JAVA_HOME /home/jdk1.8.0_151
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8066
CMD /home/mycat/bin/mycat console

3.2 构建镜像

# 构建
docker build -t mycat:2020-latest -f mycatDockerfile 

# Mycat启动方式有两种
# 1. 控制台方式启动(可以看到执行记录信息)
./mycat console 
# 2. 后台启动
./mycat start

3.3 测试运行镜像

# 1. 启动
docker run -it --name=mycat -p 8066:8066 镜像ID

# 2. 我们先把conf配置和logs日志目录copy到宿主机,主要是我们启动的时候挂载宿主机,方便配置和查看日志
docker cp mycat:/home/mycat/conf/ /root/mycat/
docker cp mycat:/home/mycat/logs/ /root/mycat/

# 3. 创建
docker run -it --name=mycat_1 -p 8066:8066 \
	-v /root/mycat/conf/:/home/mycat/conf/ 
	-v /root/mycat/logs/:/home/mycat/logs/ 
	镜像ID

三、Docker 私有仓库搭建

  • Docker 私有仓库 主要是企业内部用来存放镜像的仓库,相对官方仓库以及阿里云仓库,具有更高的保密安全级别;

1. 创建私有仓库

# 1. 拉取私有仓库镜像(私有仓库程序本身就是一个镜像)
docker pull registry
# 2. 启动私有仓库容器
docker run -di --name=registry_1 -p 5000:5000 镜像ID
# 3. 测试
http://192.168.1.112:5000/v2/_catalog
# 4. 修改daemon.json,让docker信任私有仓库地址
"insecure-registries": ["192.168.1.112:5000"]
# 5. 修改配置后重启docker
systemctl restart docker

2. 测试私有仓库

# 1. 标记此镜像为私有仓库的镜像
docker tag tomcat:8 192.168.1.104:5000/tomcat-8
# 2. 上传镜像到私有仓库
docker push 192.168.1.104:5000/tomcat-8
# 3. 删除192.168.1.104:5000/tomcat-8本地仓库镜像
docker rmi -f 192.168.1.104:5000/tomcat-8
# 4. 从私有仓库拉取192.168.1.104:5000/tomcat-8镜像,并运行
docker run -it -p 8080:8080 192.168.1.104:5000/tomcat-8
# 5. 浏览器测试
http://192.168.1.112:8080