一、commit封装镜像
我们以ubuntu的镜像为例:
首先有ubentu的镜像
[root@server1 ~]# docker images ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 07c86167cdc4 3 years ago 188MB
我们先建立vm1容器,然后对其进行一些操作,然后ctrl+p+q退出
[root@server1 ~]# docker run -it --name vm1 ubuntu
root@6074aca22100:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@6074aca22100:/# touch file{1..10}
root@6074aca22100:/# 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
在上面的基础上我们删除vm1容器,然后重新建立,查看建立的文件是否还存在
[root@server1 ~]# docker rm -f vm1
vm1
[root@server1 ~]# docker run -it --name vm1 ubuntu
root@94a7b7a6ffc0:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
我们可以发现我们创建的文件没有了,我们的操作没有被保存。
那么我们如果需要让其继续存在就需要重新建立,然后重新commit封装即可
root@94a7b7a6ffc0:/# touch file{1..10}
root@94a7b7a6ffc0:/# 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
ctrl+d释放资源退出,封装镜像
root@94a7b7a6ffc0:/# exit
[root@server1 ~]# docker commit -m "add files" vm1 ubuntu:v1
sha256:387e3d445215ca2e177b4c8f0ae3807edffd919a13be237ebcc5e69c4f1523b8
然后我们用我们重新封装的镜像来运行容器。
[root@server1 ~]# docker run -it --name vm2 ubuntu:v1
root@a5fe8bd9c26b:/# 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
我们可以发现我们之前的文件依旧被保存了下来
二、Dockerfile的编写,封装镜像
在之前清理之前的实验环境
docker rm -f vm1
docker rm -f vm2
docker ps -a
docker rmi ubuntu:v1
- 编写Dockerfile实现安装httpd
1.导入rhel7的镜像
[root@server1 ~]# docker load -i rhel7.tar
e1f5733f050b: Loading layer 147.1MB/147.1MB
2.编写Dockerfile
[root@server1 ~]# docker load -i rhel7.tar
e1f5733f050b: Loading layer 147.1MB/147.1MB
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM rhel7 #源镜像是rhel7,最好将rhel7的镜像放在本地
COPY yum.repo /etc/yum.repos.d/yum.repo ##复制一个yum源
RUN rpmdb --rebuilddb && yum install -y httpd ##执行命令安装httpd并清除yum缓存
##rpmdb命令用于初始化和重建rpm数据库 --rebuilddb 从已安装的包头文件,反向重建RPM数据库
EXPOSE 80 ##定义端口
CMD ["/usr/sbin/httpd","-D","FOREGROUND"] #打开apache服务-D是全局文件/etc/sysconfig/httpd中打开的参数
3.编写yum.repo(当前目录下)
[root@server1 docker]# vim yum.repo
[root@server1 docker]# ca yum.repo
-bash: ca: command not found
[root@server1 docker]# cat yum.repo
[rhel7.3]
name=rhel7.3
baseurl=http://172.25.66.250/rhel7.3
gpgcheck=0
4.封装镜像,并且测试能否使用
[root@server1 docker]# docker build -t rhel7:v1 .
注意后面的点,表示当前目录,我们设置其标签为v1
最后我们可以发现编写成功
[root@server1 docker]# docker images rhel7:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 v1 41e959659080 2 minutes ago 193MB
5.我们使用新的镜像来运行一个新的容器,并将httpd默认发布文件所在目录挂载到httpd的默认发布目录下
[root@server1 ~]# cd /tmp/docker/
[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 vm1 -p 80:80 -v /tmp/docker/web/:/var/www/html rhel7:v1
3f1d0e90e349c373c879f361476e81ed2922637035de56962041053bb423d80d
[root@server1 docker]# curl 172.25.66.1
hello
hello
hello
6.我们修改默认发布文件,然后继续访问测试
[root@server1 docker]# cd web/
[root@server1 web]# echo www.ljz.org > index.html
[root@server1 web]# curl 172.25.66.1
www.ljz.org
我们可以发现只要我们修改默认发布界面即可
三、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 ~]# ls
busybox.tar docker game2048.tar nginx.tar rhel7.tar ubuntu.tar
[root@server1 ~]# docker load -i busybox.tar
8a788232037e: Loading layer 1.37MB/1.37MB
Loaded image: busybox:latest
2.编写Dockerfile文件
[root@server1 docker]# ls
Dockerfile web yum.repo
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world #设置环境变量
ENTRYPOINT echo "hello,$name"
3.建立镜像,运行容器
[root@server1 docker]# docker run --rm busybox:v1 #运行容器后删除
hello,world
4.在这里有必要说明一个问题,我们刚才在输出的时候用到的是echo,他其实是shell格式的一种,当然我们还可以使用exec格式的输出,shell格式底层会调用/bin/sh -c 来执行命令,可以解析变量,而exec时不可以解析变量的
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo","hello,$name"]
那么如果我们一定要使用exec的格式呢,我们可以这样
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]
5.使用ENTRYPOINT和CMD
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
当然,我们cmd的内容还可以被覆盖的