Dockerfile 知识总结

镜像结构

MySQL 5.7 为例:

基础镜像(BaseImage)
定义:应用依赖的系统函数库、环境、配置、文件等

/etc  /lib  /proe  /bin  ...   
Ubuntu 16.4  BaseImage
层(Layer)
在BaseImage 基础上添加安装包、依赖、配置等,每次操作都形成新的一层

copy ./mysql-5.7.rpm  /tmp/
RUN rpm -ivh install mysql-server.rpm && touch  /etc/my.cnf  && ...
EntryPoint systemctl start mysql
入口(Entrypoint)
镜像运行入口,一般是程序启动的脚本和参数

MySql 5.7

Dockerfile 基础语法

官方网址
https://docs.docker.com/engine/reference/builder/#dockerignore-file
FROM
说明:指定基础镜像,一般出现在dockerfile 文档的第一行

例:
FROM centos:7
ENV
说明:设置环境变量,可在后面指令使用

格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

例:
ENV VERSION 1.0
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
COPY
说明:拷贝本地文件到镜像的制定目录

格式:
COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]

例:
COPY ./mysql-5.7.rpm  /tmp
RUN
说明:执行Linux的shell 命令,一般是安装过程的命令

例:
RUN yum install gcc
CMD
说明:CMD 容器启动命令,和RUN 命令相似

格式:
shell 格式: CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]

注意:如果使用CMD shell 格式 实际的命令会被包装为 sh -c 的参数的形式进行执行。
例:
CMD echo $HOME

在实际执行中,会将其变更为:
CMD [ "sh", "-c", "echo $HOME" ]
EntryPoint
说明:镜像中应用的启动命令,容器运行时调用,与CMD 有些相似,但是也存在使用上的不同

例:
ENTRYPOINT java -jar xx.jar
EntryPoint 与 CMD 对比
案例 1:
***** dockerfile 文件  【CMD】
FROM ubuntu:16.04 

RUN apt-get update \ 
&& apt-get install -y curl \ 
&& rm -rf /var/lib/apt/lists/* 

CMD [ "curl", "-s", "http://ip.cn" ]
*****

$ docker run myip -i
docker: Error response from daemon: invalid header field value " oci runtime error: container_linux.go:247: starting container pr ocess caused \"exec: \\\"-i\\\": executable file not found in $P ATH\"\n

原因:可以看到可执行文件找不到的报错, executable file not found 。之前 我们说过,跟在镜像名后面的是 command ,运行时会替换 CMD 的默认值。因此 这里的 -i 替换了原来的 CMD ,而不是添加在原来的 curl -s http://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。

正确操作:
$ $ docker run myip curl -s http://ip.cn -i


案例2:
***** dockerfile 文件 【EntryPoint】
FROM ubuntu:16.04 

RUN apt-get update \ 
&& apt-get install -y curl \ 
&& rm -rf /var/lib/apt/lists/* 

ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
*****

$docker run myip -i
HTTP/1.1 200 OK 
Server: nginx/1.8.0 
Date: Tue, 22 Nov 2016 05:12:40 GMT 
Content-Type: text/html; charset=UTF-8 
Vary: Accept-Encoding 
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
......

综上所得:当存在 ENTRYPOINT 后, CMD 的内容将会作为参数传给 ENTRYPOINT ,而这里 -i 就是新的 CMD ,因此会作为参数传给 curl

dockerfile 总结

  • Dockerfile 的本质是一个文件,通过指令描述镜像的构建过程
  • Dockerfile的第一行必须是FROM,从一个基础镜像来构建
  • 基础镜像可以是基本操作系统,如Ubuntu。也可以是其他人自作号的镜像,例如:java:8-alpine

dockerfile 案例一

dockerfile 文档
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar

# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8

# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
控制台执行操作
# 传建一个目录,存放程序运行需要的文件
$ mkdir docker-demo

# finalShell 拖拽上传指定文件 (3个)
- docker-demo.jar  
- Dockerfile
- jdk8.tar.gz

# 镜像构建命令执行
# 第二个 . 是 dockerfile 所在文件路径
$ docker build -t javaweb:1.0 .

# 查看构建好的镜像内容
$ docker images

dockerfile 案例二

dockerfile 文档
# 指定基础镜像
FROM java:8-alpine

# 拷贝java 项目包
COPY ./app.jar /tmp/app.jar

# 暴露端口
EXPOSE 8090

# 入口,java 项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
控制台执行操作
# 进入docker-demo 文件目录
$ cd docker-demo

# finalShell 拖拽上传Dockerfile文件进行覆盖
- Dockerfile

# 镜像构建命令执行
# 第二个 . 是 dockerfile 所在文件路径
docker build -t javaweb:2.0 .

# 查看构建好的镜像内容
$ docker images

posted on 2022-09-13 11:08  cloud_wh  阅读(70)  评论(0编辑  收藏  举报

导航