简介
定义
- 用来构建docker 镜像的文件
构建步骤
- 编写一个dockerfile 文件
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像 (DockerHub, 阿里云镜像仓库)
基础知识
- 每个保留关键字 (指令) 都必须是大写字母
- 从上倒下顺序执行
表示注释
- 每一个指令都会创建提交一个新的镜像层并提交
DockerFile 是面向开发的, 之后需要发布项目, 做镜像, 就需要编写dockerfile 文件, 且逐渐成为了企业交付的标准
关系
DockerFile: 构建文件, 定义了一切的步骤, 源代码
- DockerImages: 通过DockerFile 构建生成的镜像, 最终发布和运行的产品, 原来是jar, war
- Docker 容器: 容器就是镜像运行起来提供服务
指令
| 指令 | 含义 |
|---|---|
| FROM | 基础镜像, 一切从这里开始构建 |
| MAINTAINER | 镜像是谁写的, 姓名 + 邮箱 |
| RUN | Docker 镜像构建时需要运行的命令 |
| ADD | 添加内容 e.g. 添加 tomcat 压缩包, ADD 后需要跟上tomcat 压缩包, 格式: ADD source_dir/file dest_dir/file |
| WORKDIR | 镜像的工作目录 格式: WORKDIR path_dir |
| VOLUME | 挂载目录 |
| EXPOSE | 端口配置 |
| CMD | 指定启动容器时需要运行的命令 (只有最后一个会生效, 可以被替代) e.g. docker run -l 在容器运行时, CMD ls -a, 这时 -l 会替代 ls -a |
| ENTRYPOINT | 指定启动容器时需要运行的命令 (可以追加命令) e.g. 如上, -l 会追加到 ls -a 后, 形成ls -a -l 命令 |
| ONBUILD | 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令, 触发指令 |
| COPY | 类似ADD, 将文件拷贝到镜像中 格式: COPY source_dir/file dest_dir/file |
| ENV | 构建时设置环境变量 格式: ENV key value |
| ARG | 设置编译镜像时加入的参数 格式: ARG variable |
实战测试
- Docker Hub 中99% 的镜像都是以sretch 为基础镜像

- 创建一个自己的centos:
- 编写dockerfile:
```shell
因为不写版本导致使用了最新版本的镜像, 在后面执行yum install 时就会报下载失败, 没有mirror url 的地址
FROM centos:7 MAINTAINER flmfuliming018@icloud.com
- 编写dockerfile:
```shell
ENV MYPATH /usr/local WORKDIR $MYPATH
RUN yum -y install vim RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH CMD echo “——end——“ CMD /bin/bash
b. 通过这个文件构建镜像```shell#-f: 后面跟dockerfile 文件路径#-t: 后面跟镜像名:[tag]docker build -f mydockerfile-centos -t mycentos:0.1 .

c. 启动自定义镜像, 观察dockerfile 中的配置
- 可以使用ifconfig 命令
- 可以使用vim 命令
- 已进入系统, 默认工作路径为/usr/local
History 命令
- 作用:
- 查看镜像生成步骤
语法:
docker history 镜像ID
效果:

CMD 与ENTRYPOINT 的区别
测试CMD (只有最后一个命令会被运行)
编写dockerfile
FROM centosCMD ["ls", "-a"]
构建镜像
docker build -f dockerfile-cmd-test -t cmdtest:0.1 .
启动容器
docker run cmdtest:0.1#以下是容器启动后的提示....dockerenvbindevetchomeliblib64lost+foundmediamntoptprocrootrunsbinsrvsystmpusrvar
错误示范: 想在ls -a 命令之后追加参数-l, 发现错误
docker run cmdtest:0.1 -l#出现以下错误:#原因: 使用CMD 命令的情况下, 会将ls -a 替换成-l, 而-l 不是一条完整的命令, 就会报错container_linux.go:235: starting container process caused "exec: \"-l\": executable file not found in $PATH"/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"-l\": executable file not found in $PATH".ERRO[0000] error getting events from daemon: net/http: request canceled
正确写法:
#写成ls -aldocker run cmdtest:0.1 ls -al#产生以下提示total 0drwxr-xr-x. 1 root root 17 Feb 1 08:06 .drwxr-xr-x. 1 root root 17 Feb 1 08:06 ..-rwxr-xr-x. 1 root root 0 Feb 1 08:06 .dockerenvlrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bindrwxr-xr-x. 5 root root 340 Feb 1 08:06 devdrwxr-xr-x. 1 root root 66 Feb 1 08:06 etcdrwxr-xr-x. 2 root root 6 Nov 3 2020 homelrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/liblrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64drwx------. 2 root root 6 Sep 15 14:17 lost+founddrwxr-xr-x. 2 root root 6 Nov 3 2020 mediadrwxr-xr-x. 2 root root 6 Nov 3 2020 mntdrwxr-xr-x. 2 root root 6 Nov 3 2020 optdr-xr-xr-x. 213 root root 0 Feb 1 08:06 procdr-xr-x---. 2 root root 162 Sep 15 14:17 rootdrwxr-xr-x. 1 root root 21 Feb 1 08:06 runlrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbindrwxr-xr-x. 2 root root 6 Nov 3 2020 srvdr-xr-xr-x. 13 root root 0 Feb 1 06:30 sysdrwxrwxrwt. 7 root root 171 Sep 15 14:17 tmpdrwxr-xr-x. 12 root root 144 Sep 15 14:17 usrdrwxr-xr-x. 20 root root 262 Sep 15 14:17 var
测试ENTRYPOINT
编写dockerfile
FROM centosENTRYPOINT ["ls", "-a"]
构建镜像
docker build -f dockerfile-cmd-entrypoint -t entrypoint-test:0.1 .#产生以下提示, 说明镜像生成成功Sending build context to Docker daemon 4.096 kBStep 1/2 : FROM centos:7---> eeb6ee3f44bdStep 2/2 : ENTRYPOINT ls -a---> Running in 36fd4f02cd9d---> 66afa7c89a03Removing intermediate container 36fd4f02cd9dSuccessfully built 66afa7c89a03
启动容器
docker run entrypoint-test:0.1#以下是容器启动后的提示....dockerenvbindevetchomeliblib64lost+foundmediamntoptprocrootrunsbinsrvsystmpusrvar
- 在run 命令后添加需要追加的参数:
#会拼接在ENTRYPOINT 的命令后docker run entrypoint-test:0.1 -ltotal 12drwxr-xr-x. 1 root root 17 Feb 1 08:08 .drwxr-xr-x. 1 root root 17 Feb 1 08:08 ..-rwxr-xr-x. 1 root root 0 Feb 1 08:08 .dockerenv-rw-r--r--. 1 root root 12114 Nov 13 2020 anaconda-post.loglrwxrwxrwx. 1 root root 7 Nov 13 2020 bin -> usr/bindrwxr-xr-x. 5 root root 340 Feb 1 08:08 devdrwxr-xr-x. 1 root root 66 Feb 1 08:08 etcdrwxr-xr-x. 2 root root 6 Apr 11 2018 homelrwxrwxrwx. 1 root root 7 Nov 13 2020 lib -> usr/liblrwxrwxrwx. 1 root root 9 Nov 13 2020 lib64 -> usr/lib64drwxr-xr-x. 2 root root 6 Apr 11 2018 mediadrwxr-xr-x. 2 root root 6 Apr 11 2018 mntdrwxr-xr-x. 2 root root 6 Apr 11 2018 optdr-xr-xr-x. 214 root root 0 Feb 1 08:08 procdr-xr-x---. 2 root root 114 Nov 13 2020 rootdrwxr-xr-x. 1 root root 21 Feb 1 08:08 runlrwxrwxrwx. 1 root root 8 Nov 13 2020 sbin -> usr/sbindrwxr-xr-x. 2 root root 6 Apr 11 2018 srvdr-xr-xr-x. 13 root root 0 Feb 1 06:30 sysdrwxrwxrwt. 7 root root 132 Nov 13 2020 tmpdrwxr-xr-x. 13 root root 155 Nov 13 2020 usrdrwxr-xr-x. 18 root root 238 Nov 13 2020 var
实战: Tomcat 镜像
- 准备镜像文件 tomcat 压缩包, jdk 的压缩包

- 编写docker 文件
- 命名: 最好使用Dockerfile, 这样在build 时不需要添加-f 参数, docker 会自动寻找Dockerfile 文件 ```shell FROM centos:7 MAINTAINER flmfuliming018@icloud.com
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u321-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.58.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_321 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.58 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.58 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.58/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.58/logs/catalina.out
3. 生成镜像```shelldocker build -t diytomcat .
看到以下提示说明生成镜像成功
启动容器
#这里的挂载了两个数据卷, 目录映射关系如下所示:# 外部 -> 内部#1. /home/flm/build/tomcat/test -> /usr/local/apache-tomcat-9.0.58/webapps/test#2. /home/flm/build/tomcat/logs -> /usr/local/apache-tomcat-9.0.58/webapps/logsdocker run -p 9090:8080 --name flmtomcat01 -v /home/flm/build/tomcat/test:/usr/local/apache-tomcat-9.0.58/webapps/test -v /home/flm/build/tomcat/logs:/usr/local/apache-tomcat-9.0.58/webapps/logs diytomcat
访问测试
curl docker 服务器IP:9090
发布项目 (由于做了卷挂载, 可以直接在本地编写项目就可以发布)
编辑web.xml, 并放在/home/flm/build/tomcat/test/WEB-INF 目录下
<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_3_0.xsd"version="3.0"metadata-complete="true"></web-app>
编辑index.jsp, 并放在/home/flm/build/tomcat/test 目录下
<html> <head> <title>第一个 JSP 程序</title> </head> <body> <% out.println("Hello World!"); %> </body> </html>
- 访问测试: docker 服务器IP:9090/test

日志同步如下:
- 注: 访问之前先指定setenfore 0, 不然从容器中无法打开宿主机的index.jsp 文件, 就会导致tomcat 报403 错误, 这是因为docker 的启动参数中带了selinux=enable 的原因, 具体的解释参照: https://www.cnblogs.com/elnino/p/10845449.html
大致的意思是根据selinux label 不同, 从容器访问到的宿主机资源也不同
发布自己的镜像
发布到docker hub
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry
Options: —help Print usage -p, —password string Password -u, —username string Username

3. 登录完毕后, 使用docker push 命令提交镜像
```shell
#命令模版
docker push 账号名/镜像名:版本号
#命令实例
docker push flm/diytomcat:1.0

注: 因为虚拟机的关系, 无法连接到docker hub, 导致push 失败
发布到阿里云镜像服务
- 登录阿里云
- 找到容器镜像服务
- 创建命名空间 -> 创建镜像仓管 -> 选择本地仓库

- 浏览仓库, 查看push 步骤

总结

