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