前言:
我们以ubuntu的镜像包为示例:
首先导入ubuntu的镜像包
[root@server1 ~]# docker load -i ubuntu.tar
我们先建立vm2容器,对vm2做一些改变后,ctrl+p+q退出:
[root@server1 ~]# docker run -it --name vm2 ubuntu
root@dd43ebb4bd3f:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@dd43ebb4bd3f:/# mkdir file{1..10}
root@dd43ebb4bd3f:/# ls
bin dev file1 file2 file4 file6 file8 home lib64 mnt proc run srv tmp var
boot etc file10 file3 file5 file7 file9 lib media opt root sbin sys usr
一、重建镜像包
在前言的基础上,我们删除vm2重新建立容器,查看目录是否还保存
[root@server1 ~]# docker rm -f vm2
vm2
[root@server1 ~]# docker run -it --name vm2 ubuntu
root@857908e4dec6:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
可以查看目录不在了,我们的操作没有保存下来
我们重新连接到容器,建立十个文件:
[root@server1 ~]# docker container attach vm2
root@857908e4dec6:/#
root@857908e4dec6:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@857908e4dec6:/# touch file{1..10}
root@857908e4dec6:/# ls
bin dev file1 file2 file4 file6 file8 home lib64 mnt proc run srv tmp var
boot etc file10 file3 file5 file7 file9 lib media opt root sbin sys usr
ctrl+d退出。
两个快捷退出键的区别:
ctrl+d: 直接终止容器的运行。只能通过docker ps -a查看到此容器
ctrl+p+q: 在后台运行此容器,通过docker ps查看到
重建镜像包,保存操作
[root@server1 ~]# docker commit -m "add files" vm2 ubuntu:v1 #v1为版本号
可以查看到我们重建的镜像包:
我们使用我们重建的镜像包,建立容器运行:
[root@server1 ~]# docker run -it --name vm3 ubuntu:v1
可以看到,我们之前建立的文件,依然保存了下来,也就是说我们可以通过commit命令重建镜像包,并使用。
二、使用Dockerfile文件来重建镜像包
实验前:先清理一下我们的docker仓库
导入rhel7的镜像包:
[root@server1 ~]# docker load -i rhel7.tar
e1f5733f050b: Loading layer [==================================================>] 147.1MB/147.1MB
[root@server1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest e548f1a579cf 15 months ago 109MB
game2048 latest 19299002fdbe 2 years ago 55.5MB
ubuntu latest 07c86167cdc4 3 years ago 188MB
rhel7 latest 0a3eb3fde7fd 4 years ago 140MB
1、建立Dockerfile文件配置http服务:
1、我们先使用普通的方式配置
[root@server1 ~]# docker run -it --name vm1 rhel7 bash #使用bash运行
bash-4.2# cd /etc/yum.repos.d/
bash-4.2# ls
rhel7.repo
bash-4.2# vi yum.repo
[rhel]
name=rhel7.3
baseurl=http://172.25.254.1/rhel7.3
gpgcheck=0
bash-4.2# yum install httpd -y
bash-4.2# rpmdb --rebuilddb
2、使用Dockerfile文件
[root@server1 ~]# cd /tmp/
[root@server1 tmp]# ls
[root@server1 tmp]# mkdir docker
[root@server1 tmp]# cd docker/
[root@server1 docker]# vim Dockerfile
FROM rhel7
COPY yum.repo /etc/yum.repos.d/yum.repo
RUN rpmdb --rebuilddb && yum install -y httpd
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
建立yum源文件:
[root@server1 docker]# vim yum.repo
[rhel]
name=rhel7.3
baseurl=http://172.25.254.1/rhel7.3
gpgcheck=0
3、文件编写完成之后,就可以重建镜像包并设定TAG为v1,这个可以随便写,只是一个标签而已:
注意:指令最后面还有个点,表示Dockerfile文件在当前目录,不能忽略了!
[root@server1 docker]# docker build -t rhel7:v1 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM rhel7
---> 0a3eb3fde7fd
Step 2/4 : COPY yum.repo /etc/yum.repos.d/yum.repo
---> 7660a58a107e
Step 3/4 : RUN rpmdb --rebuilddb && yum install -y httpd
---> Running in dc76826293e7
Skipping unreadable repository '///etc/yum.repos.d/rhel7.repo'
Resolving Dependencies
--> Running transaction check
重建镜像包会逐步编译Dockerfile,没有问题会在最后面提示建立成功:
3、可以发现建立成功的提示后面有一个码 5632320b0b51,这个码就是rhel7镜像v1的码:
[root@server1 docker]# docker images rhel7:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 v1 5632320b0b51 2 minutes ago 193MB
4、用新建的镜像建立一个容器vm1并将httpd首页文件所在的目录挂载到httpd的默认发布目录下,做一个端口映射:
[root@server1 docker]# docker run -d --name vm1 -p 80:80 -v /tmp/docker/web/:/var/www/html rhel7:v1
478c3ef06ac830f53943ee9fc82240d59bbf938965afe84be2a0bb276ab6373a
[root@server1 docker]# cat web/index.html
<h1>redhat</h1>
我们更改web目录下的index.html文件:
[root@server1 docker]# echo www.redhat.com >> web/index.html
[root@server1 docker]# cat web/index.html
<h1>redhat</h1>
www.redhat.com
二、dockerfile常用的指令
ADD
用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像:
ADD html.tar /var/www
ADD http://ip/html.tar /var/www
ENV
设置环境变量,变量可以被后续的指令使用:
ENV HOSTNAME sevrer1.example.com
EXPOSE
如果容器中运行应用服务,可以把服务端口暴露出去:
EXPOSE 80
VOLUME
申明数据卷,通常指定的是应用的数据挂在点:
VOLUME ["/var/www/html"]
WORKDIR
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工
作目录,如果目录不存在会自动创建。
RUN
在容器中运行命令并创建新的镜像层,常用于安装软件包:
RUN yum install -y vim
CMD 与 ENTRYPOINT区别:
这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后
一个有效。
1、示例
我们首先导入一个输出字符的镜像
[root@server1 ~]# docker load -i busybox.tar
8a788232037e: Loading layer 1.37MB/1.37MB
Loaded image: busybox:latest
编写Dockerfile文件:
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world #设置环境变量
ENTRYPOINT echo "hello,$name"
重构镜像,运行容器:
[root@server1 docker]# docker build -t busybox:v1 . #重构镜像
[root@server1 docker]# docker run --rm busybox:v1 #运行容器后删除
示例2
那么使用exec格式应该怎么写呢?
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
[root@server1 docker]# docker build -t busybox:
latest v1 v2
[root@server1 docker]# docker build -t busybox:v3 .
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ENV name world
---> Using cache
---> f1ee64744d29
Step 3/3 : ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
---> Running in 2c4a7bd831bb
Removing intermediate container 2c4a7bd831bb
---> f26bdac120d1
Successfully built f26bdac120d1
Successfully tagged busybox:v3
[root@server1 docker]# docker run --rm busybox:v3
hello,world
示例3,使用ENTRYPOINT和CMD实现
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@server1 docker]# docker build -t busybox:v4 .
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ENTRYPOINT ["/bin/echo","hello"]
---> Running in 78b4664658e2
Removing intermediate container 78b4664658e2
---> 907faccc1ba8
Step 3/3 : CMD ["world"]
---> Running in a67be77994d5
Removing intermediate container a67be77994d5
---> 70bd713a0bb4
Successfully built 70bd713a0bb4
Successfully tagged busybox:v4
[root@server1 docker]# docker run --rm busybox:v4
hello world
运行容器时加入字符可以替换CMD的命令:
[root@server1 docker]# docker run --rm busybox:v4 redhat
hello redhat