我们以ubuntu的镜像包为示例:
首先导入ubuntu的镜像包
[root@docker1 ~]# docker load -i ubuntu.tar
我们先建立vm2容器,对vm2做一些改变后,ctrl+p+q退出:
[root@docker1 ~]# docker run -it --name vm2 ubuntu
root@2b96686281a1:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@2b96686281a1:/# mkdir file{1..10}
root@2b96686281a1:/# ls
bin etc file2 file5 file8 lib mnt root srv usr
boot file1 file3 file6 file9 lib64 opt run sys var
dev file10 file4 file7 home media proc sbin tmp
root@2b96686281a1:/#
root@2b96686281a1:/# [root@docker1 ~]#
一、重建镜像包
在前面的基础上,我们删除vm2重新建立容器,查看目录是否还保存
[root@docker1 ~]# docker rm -f vm2
vm2
[root@docker1 ~]# docker run -it --name vm2 ubuntu
root@d5d0e82ec0b6:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@d5d0e82ec0b6:/#
可以查看目录不在了,我们的操作没有保存下来
我们重新连接到容器,建立十个文件:
[root@docker1 ~]# docker container attach vm2
root@d5d0e82ec0b6:/#
root@d5d0e82ec0b6:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@d5d0e82ec0b6:/# touch file{1..10}
root@d5d0e82ec0b6:/# ls
bin file1 file4 file8 lib64 proc srv var
boot file10 file5 file9 media root sys
dev file2 file6 home mnt run tmp
etc file3 file7 lib opt sbin usr
root@d5d0e82ec0b6:/#
ctrl+d退出。
两个快捷退出键的区别:
- ctrl+d: 直接终止容器的运行。只能通过docker ps -a查看到此容器
- ctrl+p+q: 在后台运行此容器,通过docker ps查看到
重建镜像包,保存操作
[root@docker1 ~]# docker commit -m "add files" vm2 ubuntu:v1 #v1为版本号
可以查看到我们重建的镜像包:
我们使用我们重建的镜像包,建立容器运行:
[root@docker1 ~]# docker run -it --name vm3 ubuntu:v1
可以看到,我们之前建立的文件,依然保存了下来,也就是说我们可以通过commit命令重建镜像包,并使用。
二、使用Dockerfile文件来重建镜像包
实验前:先清理一下我们的docker仓库
导入rhel7的镜像包:
[root@docker1 ~]# docker load -i rhel7.tar
e1f5733f050b: Loading layer 147.1MB/147.1MB
[root@docker1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 07c86167cdc4 3 years ago 188MB
rhel7 latest 0a3eb3fde7fd 4 years ago 140MB
[root@docker1 ~]#
1、建立Dockerfile文件配置http服务:
1、我们先使用普通的方式配置
[root@docker1 ~]# 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
======================
[rhel7]
name=rhel7
baseurl=http://172.25.70.250/rhel7.3
gpgcheck=0
============================
bash-4.2# yum install -y httpd
bash-4.2# rpmdb --rebuilddb
2、使用Dockerfile文件
[root@docker1 ~]# cd /tmp/
[root@docker1 tmp]# ls
[root@docker1 tmp]# mkdir docker
[root@docker1 tmp]# cd docker/
[root@docker1 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"]
=================================
[root@docker1 docker]# vim yum.repo
=================================
[rhel]
name=rhel7.3
baseurl=http://172.25.70.250/rhel7.3
gpgcheck=0
3、文件编写完成之后,就可以重建镜像包并设定TAG为v1,这个可以随便写,只是一个标签而已:
注意:指令最后面还有个点,表示Dockerfile文件在当前目录,不能忽略了!
[root@docker1 docker]# docker build -t rhel7:v1 .
重建镜像包会逐步编译Dockerfile,没有问题会在最后面提示建立成功:
3、可以发现建立成功的提示后面有一个码72f206cf2e47,这个码就是rhel7镜像v1的码:
[root@docker1 docker]# docker images rhel7:v1
4、用新建的镜像建立一个容器vm1并将httpd首页文件所在的目录挂载到httpd的默认发布目录下,做一个端口映射:
[root@docker1 docker]# mkdir web
[root@docker1 docker]# vim web/index.html
=========================================
taylor
=========================================
[root@docker1 docker]# docker run -d --name vm1 -p 80:80 -v /tmp/docker/web/:/var/www/html rhel7:v1
我们更改web目录下的index.html文件:
[root@docker1 docker]# echo www.taylorswift.com >> web/index.html
[root@docker1 docker]# cat web/index.html
taylor
www.taylorswift.com
[root@docker1 docker]#
二、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@docker1 ~]# docker load -i busybox.tar
8a788232037e: Loading layer 1.37MB/1.37MB
Loaded image: busybox:latest
[root@docker1 ~]#
编写Dockerfile文件:
[root@docker1 ~]# cd /tmp/docker/
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT echo "hello,$name"
重构镜像,运行容器:
#重构镜像
[root@docker1 docker]# docker build -t busybox:v1 .
#运行容器后删除
[root@docker1 docker]# docker run --rm busybox:v1
示例2
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT echo "hello,$name"
[root@docker1 docker]# docker build -t busybox:v1 .
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ENV name world
---> Running in cc0531ebdd94
Removing intermediate container cc0531ebdd94
---> c3c0516de4d7
Step 3/3 : ENTRYPOINT echo "hello,$name"
---> Running in 209013708a5e
Removing intermediate container 209013708a5e
---> a04506ae2cab
Successfully built a04506ae2cab
Successfully tagged busybox:v1
[root@docker1 docker]# docker run --rm busybox:v1
hello,world
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo", "hello,$name"]
[root@docker1 docker]# docker build -t busybox:v2 .
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ENV name world
---> Using cache
---> c3c0516de4d7
Step 3/3 : ENTRYPOINT ["/bin/echo", "hello,$name"]
---> Running in 84db0445c525
Removing intermediate container 84db0445c525
---> 8472a1390bb8
Successfully built 8472a1390bb8
Successfully tagged busybox:v2
[root@docker1 docker]# docker run --rm busybox:v2
hello,$name
使用exec格式的写法:
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
[root@docker1 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
---> c3c0516de4d7
Step 3/3 : ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
---> Running in 6113bfc8fd42
Removing intermediate container 6113bfc8fd42
---> 5aba3f3e6860
Successfully built 5aba3f3e6860
Successfully tagged busybox:v3
[root@docker1 docker]# docker run --rm busybox:v3
hello,world
[root@docker1 docker]#
示例3,使用ENTRYPOINT和CMD实现
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@docker1 docker]# docker build -t busybox:v4 .
Sending build context to Docker daemon 4.608kB
Step 1/4 : FROM busybox
---> 59788edf1f3e
Step 2/4 : ENV name world
---> Using cache
---> c3c0516de4d7
Step 3/4 : ENTRYPOINT ["/bin/echo","hello"]
---> Running in 28e1d34404cc
Removing intermediate container 28e1d34404cc
---> 08545bc4830b
Step 4/4 : CMD ["world"]
---> Running in 5bdd5d67a3f1
Removing intermediate container 5bdd5d67a3f1
---> d41b69b57149
Successfully built d41b69b57149
Successfully tagged busybox:v4
[root@docker1 docker]# docker run --rm busybox:v4
hello world
[root@docker1 docker]#
运行容器时加入字符可以替换CMD的命令:
[root@docker1 docker]# docker run --rm busybox:v4 redhat
hello redhat
[root@docker1 docker]#