镜像分层
每次commit或使用dockerfile都是在原有的image基础上添加新的配置。
多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
添加文件:在容器中创建文件时,新文件被添加到容器层中。
读取文件:在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化
的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修
改,所以镜像可以被多个容器共享。
docker在/var/lib/docker/overlay2中创建容器名-init的目录,当用户创建容器时,docker-engin在/var/lib/docker/overlay2中创建容器同名的目录,在新创建的目录中记录docker的变化的文件
持久化存储
1.把宿主机文件系统里的目录映射到容器内的目录。容器内在该目录里创建的所有文件,都存储到宿主机的对应目录中,在关闭容器后,宿主机的目录依然存在,再次启动容器时还能读取到之前创建的文件,因此实现了容器的文件持久化。当然同时要明白,如果是对镜像自带文件进行了修改,由于镜像是只读的,该修改操作无法在关闭容器时保存下来,除非在修改了文件后构建一个新的镜像。
2.把多台宿主机的磁盘目录通过网络联合为共享存储,然后把共享存储中的特定目录映射给特定的容器,这样容器在重启时,还是能读取到关闭前创建的文件。生产环境中常用NFS作为共享存储方案。
挂载的两种方法:
1.挂载时创建卷
docker run -d -p 8000:80 --name uts1 -v /data:/usr/share/nginx/html nginx
在/data中
echo "test.thml" > index.html
2.先创建卷后挂载
docker volume create --name volm1 #创建卷
docker volume ls #查看卷名
docker volume inspect nginx #查看卷路径
docker run -d -p 9000:80 --name uts2 -v volm1:/usr/share/nginx/html
nginx
实现共享卷挂载
docker run -d -p 8080:80 --name uts3 --volumes-from uts2 nginx
原理为使用指定的容器的挂载方法,而不是让容器挂载到本容器
dockerfile
Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取 Dockerfile 中的指令自动生成映像。
Dockerfile 的基本结构
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。
常用指令
FROM:指定基础镜像,必须为第一个命令
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
MAINTAINER: 维护者信息
MAINTAINER mr_eden <mr_eden@163.com>
RUN:构建镜像时执行的命令
RUN yum update
RUN ["/etc/execfile", "arg1", "arg1"]
RUN 指令创建的中间镜像会被缓存,并会在下次构建中使用。使用--no-cache不使用缓存
ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源
ADD test /absoluteDir/
CMD:构建容器后调用,也就是在容器启动时才进行调用。
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去"application",只使用参数。
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
LABEL:用于为镜像添加元数据
LABEL <key>=<value> <key>=<value> <key>=<value>
ENV:设置环境变量
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能
设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如
果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
EXPOSE:指定于外界交互的端口
EXPOSE 11211/tcp 11211/udp
EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
VOLUME:用于指定持久化目录
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以在容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它
WORKDIR:工作目录,类似于cd命令
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
USER:指定运行容器时的用户名或 UID
USER www
ARG:用于指定传递给构建运行时的变量
ARG site
ARG build_user=www
ONBUILD:用于设置镜像触发器
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发
使用dockerfile建立nginx镜像
创建dockerfile时,应位于目录末端
vim Dockerfile
FROM centos7:v1
MAINTAINER rourou
ENV PATH /usr/local/nginx/sbin:$PATH
ADD nginx-1.16.1.tar.gz /usr/local/
RUN yum -y install epel-release.noarch
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www
WORKDIR /usr/local/nginx-1.16.1
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
docker build -t nginx:v1 .
使用dockerfile建立httpd镜像
vim run.sh
#!/bin/bash
/usr/sbin/sshd &
/usr/local/apache2/bin/httpd -D FOREGROUND
vim Dockerfile
FROM centos7:v1
MAINTAINER rourou
RUN yum -y install wget
WORKDIR /usr/local/src
RUN wget http://apache.fayea.com/httpd/httpd-2.4.41.tar.gz
RUN tar -zxvf httpd-2.4.41.tar.gz
WORKDIR httpd-2.4.41
RUN yum -y install epel-release.noarch && yum makecache fast
RUN yum install -y gcc make apr-devel apr apr-util apr-util-devel pcre-devel
RUN ./configure --prefix=/usr/local/apache2 --enable-mods-shared=most --enable-so
RUN make && make install
RUN sed -i 's/#ServerName www.rourou.com:80/ServerName localhost:80/g' /usr/local/apache2/conf/httpd.conf
RUN /usr/local/apache2/bin/httpd
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/run.sh
EXPOSE 80
CMD ["/usr/local/sbin/run.sh"]
docker build -t apache_dockerfile:centos .