• 【Docker第三篇】彻底搞懂Dockerfile文件


    一、前言

    本文资源地址

    二、Dockerfile基本命令

    2.1 FROM (导入基础镜像,几乎是必须的,就像是java程序中的import导入)

    FROM ubuntu:14.04 
    
    • 1

    指定基础镜像,比如FROM ubuntu:14.04

    2.2 RUN (在镜像内部执行一些命令,类似java程序中的main函数)

    RUN groupadd -r mysql && useradd -r -g mysql mysql 
    
    • 1

    在镜像内部执行一些命令,比如安装软件,配置环境等,换行可以使用""

    2.3 COPY 和 ADD (都是类似 linux cp 命令,放在一起学习)

    COPY docker-entrypoint.sh /usr/local/bin/ 
    
    • 1

    将主机的文件复制到镜像内,如果目录不存在,会自动创建所需要的目录,注意只是复制,不会提取和
    解压,类似于 linux 上的 cp 命令,对文件或目录执行 复制 操作

    ADD application.yml /etc/itcrazy2016/
    
    • 1

    更多的是将主机的文件复制到目录内,最后这个文件也被打到 image 镜像里面,用COPY也可以实现这个功能,但是ADD会对压缩文件提取和解压

    2.4 WORKDIR(类似 linux 中 mkdir xxx && cd xxx 命令)

    指定镜像的工作目录,之后的命令都是基于此目录工作(若不存在则创建),类似于是 xshell 中的 mkdir && cd 命令

    WORKDIR /usr/local   # 表示从根目录出发 mkdir /usr/local &&  cd /usr/local
    WORKDIR tomcat   # 表示从当前目录 (/usr/local) 出发,mkdir tomcat && cd tomcat
    RUN touch test.txt 
    
    • 1
    • 2
    • 3

    会在/usr/local/tomcat下创建test.txt文件

    WORKDIR /root 
    ADD app.yml test/ 
    
    • 1
    • 2

    会在/root/test下多出一个app.yml文件

    2.5 ENV (环境变量,类似springboot工程的中的环境变量)

    ENV MYSQL_MAJOR 5.7 
    
    • 1

    设置变量的值,ENV MYSQL_MAJOR 5.7,可以通过docker run --e key=value修改,后面可以直接使
    用${MYSQL_MAJOR}

    2.6 VOLUME (挂载目录,磁盘操作) 和 EXPOSE (暴露端口,网络操作)

    VOLUME /var/lib/mysql 
    
    • 1

    指定数据的挂在目录

    EXPOSE 3306
    
    • 1

    指定镜像要暴露的端口,启动镜像时,可以使用-p将该端口映射给宿主机

    2.7 LABEL (给生成的镜像打上标签)

    LABEL email="itcrazy2016@163.com" 
    LABEL name="itcrazy2016" 
    
    • 1
    • 2

    设置镜像标签

    2.8 CMD 和 ENTRYPOINT (类似,放在一起学习)

    好了,Dockerfile所有的准备工作都完成了,现在要启动这个Dockerfile,将 .jar 变成一个 image 镜像。Dockerfile中的ENTRYPOINT指令和CMD指令都可以设置容器启动时要执行的命令,但用途是有略微不同的。这两个类似于 xshell 对于可执行脚本(linux上白色是文件,绿色是可执行文件,蓝色是目录),./aa.sh 执行。

    容器启动的时候默认会执行的命令,若有多个CMD命令,则最后一个生效

    CMD ["mysqld"] 或CMD mysqld 
    
    • 1

    和CMD的使用类似

    ENTRYPOINT ["docker-entrypoint.sh"] 
    
    • 1

    和CMD的不同,docker run执行时,会覆盖CMD的命令,而ENTRYPOINT不会

    ENTRYPOINT指令和CMD指令虽然是在Dockerfile中定义,但是在构建镜像的时候并不会被执行,只有在执行docker run命令启动容器时才会起作用。

    1、在Dockerfile中,只能有一个ENTRYPOINT指令,如果有多个ENTRYPOINT指令则以最后一个为准。
    2、在Dockerfile中,只能有一个CMD指令,如果有多个CMD指令则以最后一个为准。
    3、在Dockerfile中,ENTRYPOINT指令或CMD指令,至少必有其一。

    对于每个Dockerfile文件,存在三种情况:
    情况1:Dockerfile中最后只有一条ENTRYPOINT指令;
    情况2:Dockerfile中最后只有一条CMD指令;
    情况2:Dockerfile中最后有一条ENTRYPOINT指令和CMD指令。

    参考资料:https://blog.csdn.net/u010797364/article/details/120543245
    参考资料:https://blog.csdn.net/qq_45300786/article/details/103947527

    2.9 Dockerfile常用命令小结

    开始,写一个Dockerfile文件的时候:
    第一,先一个 FORM 命令,表示导入基础镜像,几乎是必须的,就像是java程序中的import导入;
    第二,开始在 Dockerfile 中执行 RUN (在镜像内部执行一些命令,类似xshell程序中的main函数),执行 COPY 和 ADD (都是类似 linux cp 命令,放在一起学习),执行 WORKDIR(类似 linux 中 mkdir xxx && cd xxx 命令);
    第三,需要的环境环境 ENV (环境变量,类似springboot工程的中的环境变量)
    第四,VOLUME (挂载目录,磁盘操作) 和 EXPOSE (暴露端口,网络操作)
    第五,LABEL 给需要生成的image镜像打好标签
    最后,镜像完成之后,执行 CMD 和 ENTRYPOINT。

    三、看懂一个Dockerfile

    3.1 在Github上找到一个Dockerfile文件

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

    3.2 阅读一个官方的Dockerfile

    https://github.com/docker-library/mysql/blob/master/5.7/Dockerfile.debian

    #
    # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
    #
    # PLEASE DO NOT EDIT IT DIRECTLY.
    #
    
    FROM debian:buster-slim
    
    # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
    RUN groupadd -r mysql && useradd -r -g mysql mysql
    
    RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*
    
    # add gosu for easy step-down from root
    # https://github.com/tianon/gosu/releases
    ENV GOSU_VERSION 1.14
    RUN set -eux; \
    	savedAptMark="$(apt-mark showmanual)"; \
    	apt-get update; \
    	apt-get install -y --no-install-recommends ca-certificates wget; \
    	rm -rf /var/lib/apt/lists/*; \
    	dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
    	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
    	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
    	export GNUPGHOME="$(mktemp -d)"; \
    	gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
    	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
    	gpgconf --kill all; \
    	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
    	apt-mark auto '.*' > /dev/null; \
    	[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
    	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
    	chmod +x /usr/local/bin/gosu; \
    	gosu --version; \
    	gosu nobody true
    
    RUN mkdir /docker-entrypoint-initdb.d
    
    RUN set -eux; \
    	apt-get update; \
    	apt-get install -y --no-install-recommends \
    		bzip2 \
    		openssl \
    # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
    # File::Basename
    # File::Copy
    # Sys::Hostname
    # Data::Dumper
    		perl \
    		xz-utils \
    		zstd \
    	; \
    	rm -rf /var/lib/apt/lists/*
    
    RUN set -eux; \
    	key='859BE8D7C586F538430B19C2467B942D3A79BD29'; \
    	export GNUPGHOME="$(mktemp -d)"; \
    	gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
    	mkdir -p /etc/apt/keyrings; \
    	gpg --batch --export "$key" > /etc/apt/keyrings/mysql.gpg; \
    	gpgconf --kill all; \
    	rm -rf "$GNUPGHOME"
    
    ENV MYSQL_MAJOR 5.7
    ENV MYSQL_VERSION 5.7.39-1debian10
    
    RUN echo 'deb [ signed-by=/etc/apt/keyrings/mysql.gpg ] http://repo.mysql.com/apt/debian/ buster mysql-5.7' > /etc/apt/sources.list.d/mysql.list
    
    # the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
    # also, we set debconf keys to make APT a little quieter
    RUN { \
    		echo mysql-community-server mysql-community-server/data-dir select ''; \
    		echo mysql-community-server mysql-community-server/root-pass password ''; \
    		echo mysql-community-server mysql-community-server/re-root-pass password ''; \
    		echo mysql-community-server mysql-community-server/remove-test-db select false; \
    	} | debconf-set-selections \
    	&& apt-get update \
    	&& apt-get install -y \
    		mysql-server="${MYSQL_VERSION}" \
    # comment out a few problematic configuration values
    	&& find /etc/mysql/ -name '*.cnf' -print0 \
    		| xargs -0 grep -lZE '^(bind-address|log)' \
    		| xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \
    # don't reverse lookup hostnames, they are usually another container
    	&& echo '[mysqld]\nskip-host-cache\nskip-name-resolve' > /etc/mysql/conf.d/docker.cnf \
    	&& rm -rf /var/lib/apt/lists/* \
    	&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \
    	&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \
    # ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
    	&& chmod 1777 /var/run/mysqld /var/lib/mysql
    
    VOLUME /var/lib/mysql
    
    COPY docker-entrypoint.sh /usr/local/bin/
    RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
    ENTRYPOINT ["docker-entrypoint.sh"]
    
    EXPOSE 3306 33060
    CMD ["mysqld"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    四、实践:jar -> image -> container

    4.1 jar -> image -> container

    (1)创建一个Spring Boot项目
    (2)写一个controller

    @RestController
    public class DockerController {
        @GetMapping("/dockerfile")
        @ResponseBody
        String dockerfile() {
            return "hello docker";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (3)mvn clean package打成一个jar包 在target下找到"dockerfiledemo-0.0.1-SNAPSHOT.jar"

    (4)在docker环境中新建一个目录"first-dockerfile"

    (5)上传"dockerfiledemo-0.0.1-SNAPSHOT.jar"到该目录下,并且在此目录创建Dockerfile

    (6)创建Dockerfile文件,编写内容

    FROM openjdk:8 
    MAINTAINER mao
    LABEL name="dockerfile-demo" version="1.0" author="mao" 
    COPY dockerfile-demo-0.0.1-SNAPSHOT.jar dockerfile-image.jar 
    CMD ["java","-jar","dockerfile-image.jar"]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (7)基于Dockerfile构建镜像

    docker build -t test-docker-image . 
    
    • 1

    (8)基于image创建container

    docker run -d --name user01 -p 6666:8080 test-docker-image 
    
    • 1

    (9)查看启动日志

    docker logs user01 
    
    • 1

    (10)宿主机上访问

    curl localhost:6666/dockerfile 
    hello docker 
    
    • 1
    • 2

    (11)还可以再次启动一个

    docker run -d --name user02 -p 8081:8080 test-docker-image
    
    • 1

    注意1:mvn clean package 将 jar变为package
    注意2:宿主机都是当前的centos机器

    4.2 jar -> image -> container

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    五、尾声

    彻底搞懂Dockerfile文件,完成了。

  • 相关阅读:
    python封印魔法球小游戏
    什么是实时流引擎?
    分布式文件存储系统FastDFS[2]-上传和下载文件工具类
    温敏AIE双亲多肽分子/AIE磁性荧光微球/多重刺激响应性聚合物纳米微球相关制备
    体验不尽,进化不止,看视频云技术六大创新
    软件测试 | 测试工程师都能看懂的redis,进阶测试开发工程师......
    云原生微服务开发日趋成熟:有效拥抱左移以改善交付
    自动化之Java面试
    17.12 事务处理(血干JAVA系类)
    已知点的经纬度坐标计算/读取DEM高程信息/海拔高度
  • 原文地址:https://blog.csdn.net/qq_36963950/article/details/126082479