前言
在前面的文章里我们已经详细介绍了构建镜像的两种常用方式,下面我们将具体看看如何实际操作,以及镜像的优化方式。
一、commit封装镜像
以ubuntu的镜像为例:
1.导入ubuntu镜像
[root@server1 ~]# docker load -i ubuntu.tar
56abdd66ba31: Loading layer [==================================================>] 196.8MB/196.8MB
9468150a390c: Loading layer [==================================================>] 208.9kB/208.9kB
11083b444c90: Loading layer [==================================================>] 4.608kB/4.608kB
5f70bf18a086: Loading layer [==================================================>] 1.024kB/1.024kB
Loaded image: ubuntu:latest
2.建立容器vm1,运行ubuntu,并建立文件,然后ctrl+p+q退出
[root@server1 ~]# docker run -it --name vm1 ubuntu
root@9d9659548963:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@9d9659548963:/# mkdir test
root@9d9659548963:/# cd test/
root@9d9659548963:/test# ls
root@9d9659548963:/test# touch file{1..10}
root@9d9659548963:/test# ls
file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
3.在上面的基础上我们删除vm1容器,然后重新建立,查看建立的文件是否还存在
[root@server1 ~]# docker rm -f vm1
vm1
[root@server1 ~]#
[root@server1 ~]# docker run -it --name vm1 ubuntu
root@36e4759bb7eb:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@36e4759bb7eb:/# cd test
bash: cd: test: No such file or directory
root@36e4759bb7eb:/#
可以看到,重新建立的容器里没有之前创建的文件
那么问题来了:如果我们得到一个原始的镜像后,需要往上百台的之机上构建容器并部署相关服务,做好的镜像没办法保存打包,那将是一件非常痛苦的事情;这个时候我们可以使用commit命令将容器构建成一个新的镜像
4.commit封装镜像
commit构建镜像三部曲:
- 运行容器
- 修改容器
- 将容器保存为新的镜像
我们直接使用上面构建的容器vm1,对它进行修改
使用commit命令进行封装
[root@server1 ~]# docker commit vm1 ubuntu:vm1
[root@server1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu vm1 9363b7554e70 11 seconds ago 188MB
5.使用新封装的镜像构建容器,保存了之前操作的痕迹
[root@server1 ~]# docker run -it --name vm2 ubuntu:vm1
root@6a924baa4aa1:/#
root@6a924baa4aa1:/#
root@6a924baa4aa1:/# 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
root@6a924baa4aa1:/#
二、编写Dockerfile构建镜像
准备工作:
删除前面构建的镜像和容器
[root@server1 ~]# docker rm -f vm1
vm1
[root@server1 ~]# docker rm -f vm2
vm2
[root@server1 ~]# docker rmi ubuntu:vm1
Untagged: ubuntu:vm1
Deleted: sha256:9363b7554e709c67de4baaef54c8b8ce2f0403f1f745eed41d3524492c1f88b3
Deleted: sha256:9e3d8f56343aee0afac55ab4dc21e1ee0c6f2780cebcd58583565ae1e7126079
开始构建:编写DockFile实现安装httpd服务
1.导入镜像
[root@server1 ~]# docker load -i rhel7.tar
2.编写Dockerfile
(1)创建放置dockfile的目录
mkdir docker
(2)编写Dockerfile文件
vim Dockerfile
FROM rhel7 # 源镜像是rhel7,最好将名为rhel7的镜像放在本地
COPY yum.repo /etc/yum.repo.d #将本地的yum源文件复制到容器中的/etc/yum.repo.d/目录下
RUN rpmdb --rebuilddb && yum install -y httpd
# 执行命令安装httpd并清除yum缓存
# rpmdb 命令用于初始化和重建rpm数据库
# --rebuilddb:从已安装的包头文件,反向重建RPM数据库
EXPOSE 80 # 定义端口为80
CMD ["/usr/share/httpd","-D","FOREGROUND"]
# 打开apach服务
# -D 是全局文件/etc/sysconfig/httpd中的打开参数
3.编写yum.repo(在当前目录下,也就是放置Dockerfile的目录中)
4.封装镜像,并测试能否正常使用
[root@server1 docker]# docker build -t rhel7:v1 . ##注意命令后有一个点,表示当前目录下
出现报错,Dokerfile内容有误
修改后重试
镜像构建成功
5.构建容器
[root@server1 docker]# docker run -d --name vm1 rhel7:v1
7fdb6ab9155b8f2afeb44b949107f685192d43f84ac98dfaf2c848565b670f53
查询IP地址
[root@server1 docker]# docker inspect vm1
书写默认发布文件,导入容器内部
[root@server1 docker]# ls
Dockerfile index.html yum.repo
[root@server1 docker]# cat index.html
snow snow snow
snow snow snow
snow snow snow
snow snow snow
snow snow snow
[root@server1 docker]#
[root@server1 docker]# docker container cp index.html vm1:/var/www/html
访问测试
curl 172.17.0.2
构建镜像,并添加数据卷挂载位置(VOLUME [“var/www/html”])
1.编写Dockerfile
[root@server1 docker]# vim Dockerfile
FROM rhel7
COPY yum.repo /etc/yum.repos.d/
RUN rpmdb --rebuilddb && yum install -y httpd
EXPOSE 80
VOLUME ["/var/www/html"]
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
2.Build构建镜像
[root@server1 docker]# docker build -t rhel7:v2 .
Sending build context to Docker daemon 4.096kB
Step 1/6 : FROM rhel7
---> 0a3eb3fde7fd
Step 2/6 : COPY yum.repo /etc/yum.repos.d/
---> Using cache ##使用了缓存
---> db0ce1a7fb77
Step 3/6 : RUN rpmdb --rebuilddb && yum install -y httpd
---> Using cache ##使用了缓存
---> ba007361f210
Step 4/6 : EXPOSE 80
---> Using cache ##使用了缓存
---> 554977c12e37
Step 5/6 : VOLUME ["/var/www/html"]
---> Running in 4fbea9452763
Removing intermediate container 4fbea9452763
---> 7094cf717b4c
Step 6/6 : CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
---> Running in 0efba909bae5
Removing intermediate container 0efba909bae5
---> 6d1e0dbaa3ff
Successfully built 6d1e0dbaa3ff
Successfully tagged rhel7:v2
这就要提到一个重要点:镜像的缓存特性
此时可以看到 rhel7:v2比 rhel7:v1多了一层
[root@server1 docker]# docker history rhel7:v1
IMAGE CREATED CREATED BY SIZE COMMENT
73f8e04e06ce About an hour ago /bin/sh -c #(nop) CMD ["/usr/sbin/httpd" "-… 0B
554977c12e37 About an hour ago /bin/sh -c #(nop) EXPOSE 80 0B
ba007361f210 About an hour ago /bin/sh -c rpmdb --rebuilddb && yum install… 52.8MB
db0ce1a7fb77 About an hour ago /bin/sh -c #(nop) COPY file:09c92a5038a23196… 71B
0a3eb3fde7fd 5 years ago 140MB Imported from -
[root@server1 docker]# docker history rhel7:v2
IMAGE CREATED CREATED BY SIZE COMMENT
6d1e0dbaa3ff 5 minutes ago /bin/sh -c #(nop) CMD ["/usr/sbin/httpd" "-… 0B
7094cf717b4c 5 minutes ago /bin/sh -c #(nop) VOLUME [/var/www/html] 0B
554977c12e37 About an hour ago /bin/sh -c #(nop) EXPOSE 80 0B
ba007361f210 About an hour ago /bin/sh -c rpmdb --rebuilddb && yum install… 52.8MB
db0ce1a7fb77 About an hour ago /bin/sh -c #(nop) COPY file:09c92a5038a23196… 71B
0a3eb3fde7fd 5 years ago 140MB Imported from -
3.生成容器,并测试是否可以正常访问
[root@server1 docker]# ls
Dockerfile index.html yum.repo
[root@server1 docker]# mkdir web
[root@server1 docker]# mv index.html web/
[root@server1 docker]# docker run -d --name vm2 -v /docker/web:/var/www/html rhel7:v2
f661d7785db9ce69e256cbe79f9c48743a4139084e4655f43ad3fc942b0d3e1f
[root@server1 docker]# curl 172.17.0.2
snow snow snow
snow snow snow
snow snow snow
snow snow snow
snow snow snow
直接在数据卷中编写发布文件
1.重新生成容器
[root@server1 docker]# docker rm -f vm2
vm2
[root@server1 docker]# docker run -d --name vm2 rhel7:v2
87e5580c7a26c9eebdd23e0da5c2394620311b0b86585814b8e40bf26dd4048d
2.查看vm2的数据卷位置
[root@server1 docker]# docker inspect vm2
3.进入数据卷位置并编写发布文件并测试
[root@server1 ~]# cd /var/lib/docker/volumes/6494e9585bee0906ca1533af3ada8d35134d2b560b3c454a114b0962604555d5/_data
[root@server1 _data]# ls
[root@server1 _data]# vim index.html
[root@server1 _data]# cat index.html
snow snow snow
snow snow snow
hello,world
只读挂载
1.建立挂载目录
[root@server1 ~]# mkdir -p /tmp/docker/web/
[root@server1 ~]# cd /tmp/docker/web/
[root@server1 web]# vim index.html
2.创建容器,并测试
[root@server1 ~]# docker run -d --name vm2 -v /tmp/docker/web:/data:ro rhel7:v2
[root@server1 ~]# docker inspect vm2
"Source": "/var/lib/docker/volumes/5da320924640e96fc6878df2d50436c532d4166acc31db2e2130624b516b6e9d/_data",
[root@server1 ~]# docker exec -it vm2 bash
bash-4.2# cd data/
bash-4.2# ls
index.html
bash-4.2# rm -rf index.html
rm: cannot remove 'index.html': Read-only file system ##只读
bash-4.2#
bash-4.2# cat index.html
snow snow snow
snow snow snow
snow snow snow
snow snow snow
bash-4.2#