小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
用来干什么?
dockerfile是用来构建docker镜像的文件,命令参数脚本。
构建步骤:
- 编写一个
dockerfile文件 docker build构建成为一个镜像docker run运行镜像docker push发布镜像(DockerHub、阿里云镜像仓库)
查看别人的dockerfile
FROM scratch
官方说明:该镜像是一个空的镜像,可以用于构建busybox等超小镜像,可以说是真正的从零开始构建属于自己的镜像。要知道,一个官方的ubuntu镜像有60MB+,CentOS镜像有70MB+
scratch不可用被pull
很多官方的镜像都是基础包,很多功能都没有,我们通常会自己搭建自己的镜像。
构建Dockerfile
基础知识
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
#表示注释- 每一层指定都会创建提交一个新的镜像层,并提交。
-
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件。Docker镜像逐渐成为企业交付的标准。 -
Dockerfile:构建文件,定义了一些步骤,源代码 -
Dockerimages:通过dockerfile构建生成镜像,最终发布和运行的产品 -
Docker容器: 容器就是镜像运行起来提供的服务器
指令
| 指令 | 说明 |
|---|---|
FROM | 基础镜像,第一行必须是FROM(除注释) |
MAINTAINER | 镜像是谁写的,姓名+邮箱 |
RUN | 镜像构建运行时候需要运行的命令 |
ADD | 添加文件到镜像内 |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载的目录 |
EXPOST | 暴露端口配置 |
CMD | 指定容器启动时候要运行的命令,只有最后一个会生效,可被替代 |
ENTRYPOINT | 指定这个容器启动的时候要运行的命令,可以追加命令 |
ONBUILD | 当构建一个被继承 Dockerfile 这个是时候就会运行 ONBUILD的指令,触发指令 |
COPY | 类似ADD,将我们的文件拷贝到镜像中 |
ENV | 构建的时候设置环境变量 |
实战测试
构建自己的ubuntu
# 编写文件
$ vim ubuntu/Dockerfile
# 基础镜像
FROM ubuntu
# 作者信息
MAINTAINER 万恶的沫白<bcjy1229@163.com>
# 环境变量
ENV MYPATH /usr/local
# 工作目录
WORKDIR $MYPATH
# 构建运行的命令
RUN apt update
RUN apt install vim -y
RUN apt install net-tools
# 对外暴露的端口
EXPOSE 80
# 指定容器启动时运行的命令
CMD echo $MYPATH
CMD echo "------end-------"
CMD /bin/bash
# 构建镜像
# -f dockerfile 文件路径
# -t 镜像名:[tag]
$ docker build -f ubuntu/Dockerfile -t myubuntu:1.0 .
...
Successfully built 42691d166ea8
Successfully tagged myubuntu:1.0
# 运行我们的镜像,并测试我们加入进去的指定是否正确
$ docker run -it myubuntu:1.0
$ pwd
/usr/local
$ vim test
我们可以列出本地镜像的变更历史
$ docker history myubuntu:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
42691d166ea8 9 minutes ago /bin/bash -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
0f5a535e3e24 9 minutes ago /bin/bash -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
235e476881da 9 minutes ago /bin/bash -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
1183c754beae 9 minutes ago /bin/bash -c #(nop) EXPOSE 80 0B
cd0475e10509 9 minutes ago /bin/bash -c apt install net-tools 1.52MB
46da59e6cabc 9 minutes ago /bin/bash -c apt install vim -y 68.2MB
5ec6fc02d873 13 minutes ago /bin/bash -c apt update 30.4MB
207d7e63bc7d 19 minutes ago /bin/bash -c #(nop) WORKDIR /usr/local 0B
8bd1c0e26d61 19 minutes ago /bin/bash -c #(nop) ENV MYPATH=/usr/local 0B
3b83db470d0f 19 minutes ago /bin/bash -c #(nop) MAINTAINER 万恶的沫白<bcj… 0B
1318b700e415 6 weeks ago /bin/bash -c #(nop) CMD ["bash"] 0B
<missing> 6 weeks ago /bin/bash -c #(nop) ADD file:524e8d93ad65f08a0… 72.8MB
通过上述方式,就可以看其他的镜像是怎么做的
CMD 和 ENTRYPOINT 区别
CMD
# 编写dockerfile 文件
$ vim ubuntu/Dockerfile-cmd
FROM ubuntu
CMD ["ls","-a"]
# 构建
$ docker build -f ubuntu/Dockerfile-cmd -t ubuntu-cmd:1.0 .
# 运行,发现ls-a 命令生效
$ docker run ubuntu-cmd:1.0
.
..
.dockerenv
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加一个命令 -l 就是 ls -al
$ docker run ubuntu-cmd:1.0 -l
# -l 命令 替换了 ["ls", "-a"] 命令,-l 不是命令所以报错
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# 需要完整命令全部替换
$ docker run ubuntu-cmd:1.0 ls -al
total 56
drwxr-xr-x 1 root root 4096 Sep 13 14:57 .
drwxr-xr-x 1 root root 4096 Sep 13 14:57 ..
-rwxr-xr-x 1 root root 0 Sep 13 14:57 .dockerenv
lrwxrwxrwx 1 root root 7 Jul 23 17:35 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Apr 15 2020 boot
drwxr-xr-x 5 root root 340 Sep 13 14:57 dev
drwxr-xr-x 1 root root 4096 Sep 13 14:57 etc
drwxr-xr-x 2 root root 4096 Apr 15 2020 home
lrwxrwxrwx 1 root root 7 Jul 23 17:35 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 23 17:35 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 23 17:35 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 23 17:35 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4096 Jul 23 17:35 media
drwxr-xr-x 2 root root 4096 Jul 23 17:35 mnt
drwxr-xr-x 2 root root 4096 Jul 23 17:35 opt
dr-xr-xr-x 341 root root 0 Sep 13 14:57 proc
drwx------ 2 root root 4096 Jul 23 17:38 root
drwxr-xr-x 5 root root 4096 Jul 23 17:38 run
lrwxrwxrwx 1 root root 8 Jul 23 17:35 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jul 23 17:35 srv
dr-xr-xr-x 13 root root 0 Sep 13 14:57 sys
drwxrwxrwt 2 root root 4096 Jul 23 17:38 tmp
drwxr-xr-x 13 root root 4096 Jul 23 17:35 usr
drwxr-xr-x 11 root root 4096 Jul 23 17:38 var
ENTRYPOINT
# 编写dockerfile 文件
$ vim ubuntu/Dockerfile-entrypoint
FROM ubuntu
ENTRYPOINT ["ls","-a"]
# 构建
$ docker build -f ubuntu/Dockerfile-entrypoint -t ubuntu-entrypoint:1.0 .
# 运行,发现ls-a 命令生效
$ docker run ubuntu-entrypoint:1.0
.
..
.dockerenv
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加命令查看运行结果,是直接拼接在 ENTRYPOINT 命令后面
$ docker run ubuntu-entrypoint:1.0 -l
total 56
drwxr-xr-x 1 root root 4096 Sep 13 14:56 .
drwxr-xr-x 1 root root 4096 Sep 13 14:56 ..
-rwxr-xr-x 1 root root 0 Sep 13 14:56 .dockerenv
lrwxrwxrwx 1 root root 7 Jul 23 17:35 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Apr 15 2020 boot
drwxr-xr-x 5 root root 340 Sep 13 14:56 dev
drwxr-xr-x 1 root root 4096 Sep 13 14:56 etc
drwxr-xr-x 2 root root 4096 Apr 15 2020 home
lrwxrwxrwx 1 root root 7 Jul 23 17:35 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 23 17:35 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 23 17:35 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 23 17:35 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4096 Jul 23 17:35 media
drwxr-xr-x 2 root root 4096 Jul 23 17:35 mnt
drwxr-xr-x 2 root root 4096 Jul 23 17:35 opt
dr-xr-xr-x 342 root root 0 Sep 13 14:56 proc
drwx------ 2 root root 4096 Jul 23 17:38 root
drwxr-xr-x 5 root root 4096 Jul 23 17:38 run
lrwxrwxrwx 1 root root 8 Jul 23 17:35 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jul 23 17:35 srv
dr-xr-xr-x 13 root root 0 Sep 13 14:56 sys
drwxrwxrwt 2 root root 4096 Jul 23 17:38 tmp
drwxr-xr-x 13 root root 4096 Jul 23 17:35 usr
drwxr-xr-x 11 root root 4096 Jul 23 17:38 var
Dockerfile中很多命令都很相似,我们需要了解他们的区别。
TOMCAT
- 准备镜像文件(
tomcat和jdk压缩包)
$ mkdir tomcat
$ wget -P tomcat/ https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.70/src/apache-tomcat-8.5.70-src.tar.gz
# 这块使用的是openjdk 13 版本,现在oracle下载挺麻烦的
$ wget -P tomcat/ https://download.java.net/openjdk/jdk13/ri/openjdk-13+33_linux-x64_bin.tar.gz
# 新建一个readme.md 文件
$ touch tomcat/readme.md
- 编写
dockerfile,官方推荐命名Dockerfile,build会自动寻找这个文件,就不需要-f指令了
FROM ubuntu
MAINTAINER 万恶的沫白<bcjy1229@163.com>
# 复制
COPY readme.md /usr/local/readme.md
# ADD 命令会自动解压
ADD apache-tomcat-8.5.70-src.tar.gz /usr/local/
ADD openjdk-13+33_linux-x64_bin.tar.gz /usr/local/
# 构建运行的命令
RUN apt update
RUN apt install vim -y
RUN apt install net-tools
# 环境变量
ENV MYPATH /usr/local
# 工作目录
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk-13
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.70-src
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.70-src
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.5.70-src/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.70-src/bin/cataline.out
- 构建
dockerfile
# 切换到Dockerfile目录内
$ cd tomcat/
# build 会自动找到Dockerfile 文件
$ docker build -t mytomcat:1.0 .
Step 1/17 : FROM ubuntu
---> 1318b700e415
Step 2/17 : MAINTAINER 万恶的沫白<bcjy1229@163.com>
---> Using cache
---> 3b83db470d0f
Step 3/17 : COPY readme.md /usr/local/readme.md
---> b6b9675a0e91
Step 4/17 : ADD apache-tomcat-8.5.70-src.tar.gz /usr/local/
---> a48391d80602
Step 5/17 : ADD openjdk-13+33_linux-x64_bin.tar.gz /usr/local/
---> 6d62b3ba173a
Step 6/17 : RUN apt update
---> Running in d9aa46bebfad
...
Step 7/17 : RUN apt install vim -y
---> Running in a5508380dd5e
...
Step 8/17 : RUN apt install net-tools
---> Running in 326f554a9ee5
...
Step 9/17 : ENV MYPATH /usr/local
---> Running in 952b410ab010
Removing intermediate container 952b410ab010
---> e707f81bc5b4
Step 10/17 : WORKDIR $MYPATH
---> Running in 8dd948af01b3
Removing intermediate container 8dd948af01b3
---> caf20ab15b73
Step 11/17 : ENV JAVA_HOME /usr/local/jdk-13
---> Running in f63dd76d3cc2
Removing intermediate container f63dd76d3cc2
---> 1279e811878f
Step 12/17 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
---> Running in 1a262572cd81
Removing intermediate container 1a262572cd81
---> 103ed5e9bab6
Step 13/17 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.70-src
---> Running in 25103bfce833
Removing intermediate container 25103bfce833
---> 10b88a4bafda
Step 14/17 : ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.70-src
---> Running in cc397ce9da3f
Removing intermediate container cc397ce9da3f
---> 16cb9a628043
Step 15/17 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
---> Running in 4aaaf5fcee14
Removing intermediate container 4aaaf5fcee14
---> 1405b496012a
Step 16/17 : EXPOSE 8080
---> Running in 80f2c6b14f51
Removing intermediate container 80f2c6b14f51
---> 84f592791304
Step 17/17 : CMD /usr/local/apache-tomcat-8.5.70-src/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.70-src/bin/cataline.out
---> Running in 2d519815484a
Removing intermediate container 2d519815484a
---> b83d4e94f683
Successfully built b83d4e94f683
Successfully tagged mytomcat:1.0
- 启动运行镜像
$ docker run -d -p 9090:8080 --name mytomcat -v /home/zbc/tomcat/test:/usr/local/apache-tomcat-8.5.70-src/webapps/test -v /home/zbc/tomcat/logs/:/usr/local/apache-tomcat-8.5.70-src/logs mytomcat:1.0
5a7f6b285654a961ed3799b3488ad6d450a294489ddd211f8c676b74ca9e78ec
出现问题需要改进
而且构建镜像不算很好,没有很好的利分层技术
发布镜像
- 先注册账号(hub.docker.com/)
- 服务器上登录账号
$ docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
# 登录账号
$ docker login -u bcjy1229
# 写密码
Password:
WARNING! Your password will be stored unencrypted in /home/zbc/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
- 在我们的服务器提交自己的镜像
$ docker push mytomcat:1.0
The push refers to repository [docker.io/library/mytomcat]
65d322d8e64d: Preparing
17253f5b73dc: Preparing
41a908891f5a: Preparing
fe17c332a35e: Preparing
3465caa6e326: Preparing
dbc9c14f1cf1: Waiting
7555a8182c42: Waiting
denied: requested access to the resource is denied
# 最后发现被拒绝了,因为dockerhub已经有很多重名的tag
# 我们重新打一个tag,必须以自己的用户名开头 username/镜像名:版本号
$ docker tag mytomcat:1.0 bcjy1229/tomcat:1.0
The push refers to repository [docker.io/bcjy1229/tomcat]
65d322d8e64d: Pushed
17253f5b73dc: Pushed
41a908891f5a: Pushed
fe17c332a35e: Pushed
3465caa6e326: Pushed
dbc9c14f1cf1: Pushed
7555a8182c42: Pushed
1.0: digest: sha256:fadfcef81b5812168fbbb8c9910a724ff529c36fe6457ae0f43f1354b620355c size: 1794
提交的时候也是按照镜像分层来提交的。