镜像是多层存储的,每一层在前一层的基础上进行修改;
容器也是多层存储,以镜像为基础层,在其基础上加一层作为容器运行时的存储层。
通过在dockerfile中定义一系列的命令和参数构成的脚本,然后这些命令应用于基础镜像,依次添加层,最终生成一个新的镜像。极大的简化了部署工作。
dockerfile主要组成部分:
1、基础镜像信息 如:FROM centos:6.8
2、制作镜像操作指令 如:RUN yum install vim -y
3、容器启动时执行指令 如:CMD [“/bin/bash”]
dockerfile指令
- FROM :指定基础镜像
- MAINTAINER :指定维护者信息,可以没有
- RUN :你想让它干什么,在命令前面加上RUN即可
- WORKDIR:就是cd命令,设置当前工作目录
- VOLUME:设置卷,挂载主机目录
容器在运行时,应该保证在存储层不写入任何数据,运行在容器内产生的数据,我们推荐是挂载,写入到宿主机上,进行维护。
#将宿主机的/data挂载到容器上
VOLUME /data
使用docker inspect "CONTAINER ID"可以查看挂载到宿主机的哪个目录。
另外,也可以通过docker run -v设置挂载的目录
- EXPOSE:指定对外端口
- CMD:指定容器启动后要干的事情
用法注意是双引号
CMD ["参数1","参数2"]
在指定了entrypoint指令后,用CMD指定具体的参数
docker不是虚拟机,容器就是一个进程,既然是进程,那么程序在启动的时候需要指定些运行参数,这就是CMD指令作用
例如centos镜像默认的CMD是/bin/bash,直接docker run -it centos会直接进入bash解释器。
也可以启动容器时候,指定参数:docker run -it centos cat /etc/os-releasea
CMD运行shell命令,也会被转化为shell形式
例如
CMD echo $PATH
会被转化为
CMD [“sh”,“-c”,“echo $PATH”]
- COPY:复制文件,和ADD一样
#COPY 宿主机文件 指定容器目录,如:
COPY 1.txt /home/
#支持多个文件,以及通配符形式复制,语法要满足Golang的filepath.Match
COPY test* /etc/te?.txt. /home/
注意:COPY指令能够保留源文件的源据,如权限,访问时间等等,这点很重要
- ADD:复制文件,和COPY一样,会自动解压
特性和COPY基本一致,不过多了些功能
1、源文件是一个URL,此时docker引擎会下载该链接,放入目标路径,且权限自动设为600,若这不是期望结果,还得增加一层RUN指令进行调整
2、源文件是一个URL,且是一个压缩包,不会自动解压,也得单独用RUN指令解压
3、源文件是一个压缩文件,且是gzip,bzip2,xz,tar情况,ADD指令会自动解压缩该文件到目标路径。
Dockerfile官方推荐使用COPY,ADD包含了更多复杂的功能,且ADD会使构建缓存失效,导致镜像构建缓慢。
- ENV和ARG:设置环境变量
ARG和ENV一样,区别在于ENV无论是在镜像构建时,还是容器运行,该变量都可以使用。
ARG只是用于构建镜像需要设置的变量,容器运行时就消失了。
dockerfile脚本,shell脚本
ENV NAME="xiaoming"
ENV AGE="18"
ENV MYSQL_VERSION=5.6
后续所有的操作,通过$NAME 就可以直接获取变量值操作了,维护dockerfile脚本时更友好,方便
- ENTRYPOINT 容器启动后执行的命令
和RUN指令一样,分为两种格式
1、exec
2、shell
作用和CMD一样,都是在指定容器启动程序以及参数。
当指定了ENTRYPOINT之后,CMD指令的语义就有了变化,而是把CMD的内容当作参数传递给ENTRYPOINT指令。
实验1
需求:通过dockerfile,构建nginx镜像,且运行容器后,生成的页面是“114514”
1、创建一个文件名为“Dockerfile”的文件。
touch Dockerfile
2、编写dockerfile文件内容
FROM nginx
RUN echo '<meta charset=utf8>114514' > /usr/share/nginx/html/index.html
3、查看镜像
docker images

图中红线就是构建好的镜像。镜像名和版本号都为none
运行以下命令可以更改镜像名和版本号
#更改镜像名和版本
docker tag "IMAGE ID" 新镜像名:版本号

4、运行镜像
#后台运行并指定端口映射
docker run -d -p 80:80 "IMAGE ID"
返回容器id就是正常运行

5、访问服务

成功!
容器内运行程序
这里要注意的是,docker不是虚拟机的概念,虚拟机里的程序运行,利用systemctl运行,但是容器内没有后台进程的概念,必须在前台运行。
容器就是为了主进程而存在的,主进程如果退出了,容器也就失去意义,自动退出。
例如,有一个经典问题
CMD systemctl start nginx
这样写是错误的,容器会立即退出
因为systemctl start nginx是希望以守护进程形式启动nginx,且CMD命令会转化为
CMD ["sh","-c","systemctl start nginx"]
这样的命令主进程是sh解释器,执行完毕后立即结束了,因此容器也就退出了。
因此正确的做法应该是
CMD ["nginx","-g","daemon off;"]
542

被折叠的 条评论
为什么被折叠?



