镜像的分层结构
仓库是用来存放镜像的,镜像是用来初始化容器的
rhel>oel> centos ubuntu debian系统
红帽和centos的区别
1.Centos是的克隆版本,是把redhat的源代码拿来编译然然后发行的发行版本。但是基本的命令和使用方法是一样。
2.centos是免费的版本,不向用户提供任何的服务,你么用户在使用工程中出现的各种问题,Centos是不负责任的。而redhat对某些服务是提供收费的,在所提供的服务中出现问题。redhat是负责解决的。
3.CentOS独有的yum命令支持在线升级,可以即时更新系统,不像RedHat那样需要花钱购买支持服务!也就是说redhat的服务是需要收费的,而Centos是完全免费的。
4.CentOS修正了许多RedHat AS的BUG。
Linux-> kernel-> diy->app不容的系统内核都是相同的(版本可能不同)但是文件系统不同
.共享宿主机的kernel
.base镜像提供的是最小的Linux发行版
.同一docker主机支持运行多种Linux发行版
.采用分层结构的最大好处是:共享资源
Copy-on-Write 可写容器层正常我们对容器进行写操作都是container这一层,下面都是只读的,但是当我们想修改下面image镜像层的时候,他是会将东西拷贝到container中然后在进行修改。
容器层以下所有镜像层都是只读的docker从上往下依次查找文件容器层保存镜像变化的部分,并不会对镜像本身进行任何修改一个镜像最多127层
镜像的构建
docker commit 构建新镜像三部曲
·运行容器
通过docker ps查看运行的容器
·修改容器
·将容器保存为新的镜像
缺点:
·效率低、可重复性弱、容易出错
·使用者无法对镜像进行审计,存在安全隐患
首先我们拉取一个新的镜像
[root@server1~]# docker pull busybox
Using default tag:latest
latest:Pulling from library/busybox
0669bedaf1fb:Pull complete Digest:sha256:b26cd013274a657b86e706210ddd5cc1f82f50155791199d29b9e86e935ce135
Status:Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
同样的我们还可以拉取其他的比如ubuntu、centos、rhel等,可以通过docker images查看打大小,但是rhel一般没有官方的,我们可以拉取别人设置的
[root@server1~]# docker pull richxsl/rhel7
[rootdserver1~]# docker images
REPOSITORY TAGIMAGE IDCREATED SIZE
nginx latested21b7a8aee 94 days ago 127MB
busybox latest83aa35ga1c793 weeks ago 1.22MB
game 2048latest19299002fdbe 3 years ago 55.5MB
richxsl/rhel7 latest9c7b3825758a 5 years ago 245MB
我们可以进行测试并查看内核版本
[root@server1~]# docker run -it --rm richxsl/rhel7 bash
[ root@ aca1620f134b/]# uname-r
3.10.0-957.e17.×8664
[ root@ aca1620f134b/]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.0(Maipo)
docker ps -a 可以获取所有的容器不用-a的话只是运行的容器
我们通过如下进入镜像
[root@server1~]# docker run -it busybox
然后我们可以创建10个文件
/#touch file1
/#1s
bin etc home root tmp var dev file1 proc sys usr
我们可以通过ctrl+D 退出,但是我们退出的话我们的容器就会被停掉,我们可以通过docker ps -a查看状态
然后我们可以通过容器的ID或者名字再次打开容器,然后通过attach连入容器
[root@server1 ~]# docker start 68097c1dd5bb
68097c1dd5bb
[root@server1~]# docker attach 68097c1dd5bb
我们也可以使用ctrl+P+Q快捷键让容器在后台运行不退出
像上述我们创建的文件都是在镜像的文件系统里面,他不会创建到本地的默认文件系统中
我们可以通过commit加上ID号将文件系统保存然在后面也可以给他起个名字
[rootaserver1 ~l# docker commit 68097cldd5bb busybox:v1
sha256:5364b27dfcc58107d4ffdd4375967229fe6495acd6846cc465240d9c9da7b1c8
我们再去查看
Lrootaserverl ~l# docker 1mages
REPOSITORY TAG IMAGE IDCREATED SIZE
busybox V1 5364b27dfcc 52 seconds ago 1.22MB
然后我们去查看他们的共享分层
先查看原始的然后去查看我们的V1发现V1只是在原始的基础上又增加了一层
如果想删除正在运行的容器的时候必须使用-f,否则就需要先停掉
[root@server1 ~]# [root@server1~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
68097c1dd5bb busybox "sh" 5minutes ago Up 3 minutes goofy montalcini
[rooteserver1~]# docker rm -f 68097c1dd5bb
68097c1dd5bb
我们也可以查看被的容器
这这个最新的nginx容器她的层数就比较多
我们创建一个dockerfile
[rooteserver1~]# mkdir docker
[root@server1~]# cd docker/
[rooteserver1 docker]#1s
[rooteserver1 docker]# vim Dockerfile
[rootaserver1 docker]#1s
Dockerfile
[rooteserverl docker]# echo westos > testfile
我们在dockerfile写上如下
FROM busybox
CoPY testfile/
我们可以先将之前建立的容器删除
[root@server1 docker]# docker rmi busybox:v1
Untagged:busybox:v1
Deleted:sha256:5364b27dfcc58107d4ffdd4375967229fe6495acd6846cc465240d9c9da7b1c8
Deleted:sha256:f0fbc4cbf6b8591662317fc8f8d01abf01893fee1839ee8d9903d6faf1c17cb3
然后我们创建一个容器通过-t指定名字
[root@server1 docker]# docker build -t demo:v1 .
我们可以发现一共执行了两步显示from busybox,然后copy文件到/下
[rootaserver1 docker]#ls
Dockerfile testfile
通过commit方式提交的镜像我们不能查看到在镜像中做了什么
但是通过dockerfile创建的镜像我们可以很清楚的看到做了什么
我么也可以对dockerfile进行重新编写我们可以再添加一句
FROM busybox
CoPY testfile/
RUN echo helloworld > filel
然后我们再构建一个build
我们可以发现v2是再v1的基础上又增加一层
Dockerfile详解
·dockerfile常用指令
·FROM
指定base镜像,如果本地不存在会从远程仓库下载。
·MAINTAINER
设置镜像的作者,比如用户邮箱等。
·COPY
把文件从build context复制到镜像支持两种形式:COPY src dest和COPY["src","dest"]
src必须指定build context中的文件或目录
·ADD
用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到
dest,也可以自动下载URL并拷贝到镜像:
ADD html.tar/var/www ADD http://ip/html.tar/var/www
首先我们将1.16版本的nginx安装包放进我们的docker文件夹中,然后我们编辑dockerfile文件
FROM busybox
ADD nginx-1.16.1.tar.gz /
然后我们build一个demo:v1
[rooteserver1 docker]# docker build -t demo:v1.
Sending build context to Docker daemon 1.036MB Step 1/2:FROM busybox
-->83aa35aalc79
Step 2/2:ADD nginx-1.16.1.tar.gz/
--->5c0bd187e65e
Successfully built 5c0bd187e65e
[root@server1 docker]# docker run -it --rm demo:v1
运行docker run发现如下
·ENV
设置环境变量,变量可以被后续的指令使用:
ENV HOSTNAME sevrer1.example.com
FROM busybox
ENV hostname server1
ADD nginx-1.16.1.tar.gz /
然后build一个v2
[root@server1 docker]# docker build -t demo:v2 .
·EXPOSE
如果容器中运行应用服务,可以把服务端口暴露出去:
EXPOSE 80
·VOLUME
申明数据卷,通常指定的是应用的数据挂载点:
VOLUME ["/var/www/html"]编辑dockerfile'如下
FROM busybox
ENV hostname server1
ADD nginx-1.16.1.tar.gz /
VOLUME ["/data"]
然后built一个v3
[root@server1 docker]# docker build -t demo:v3 .
[root@server1 docker]# docker run -it demo:v3
/ # ls
bin dev home proc sys usr
data etc nginx-1.16.1 root tmp var
/ # cd /data/
/data# 1s
/data # pwd
/data
/data# 1s
/data # touch filel
然后我们退出容器会发现容器挂载点
也就是只要容器识别到有VOUME这个卷他就自动给我们挂载上
这是我们在file1中写如内容然后去容器里面查看
[rooteserver1 data]# echo westos >> filel
[rooteserver1 data]# echo westos >> filel
[rooteserver1 data]# echo westos >> filel
[rooteserver1 datal# echo westos >> filel
[rooteserver1 _data]# cat filel westos
westos
westos
westos
westos
westos
[rootaserver1 datal# docker ps
CONTAINER ID IMAGE COMMAND CREATED ATATUS PORTS NAMES
8ebaaef0b9e8 demo:v3 "sh" 3minutes ago Up 3 minutes eloquen
t_bouman
2ffa67974075 nginx "nginx-g 'daemon of.." 6minutes ago Up 6 minutes 0.0.0.0:32768->80/tcp nginx
[rooteserver1 datal# docker attach 8e
/data# ls
filel
/data#cat filel
westos
westos
westos
westos
westos
默认挂载的文件都是读写的无论我们是在容器里面删除还是在宿主机中删除都会删除
我们可以通过 docker volume prune进行卷的删除(删掉没有被使用的卷)
·WORKDIR
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。如下我们通过workdir创建nginx目录
FROM busybox
ENV hostname server1
WORKDIR /nginx
ADD nginx-1.16.1.tar.gz/nginx
VOLUME ["/data"]
[root@server1 docker]# docker build -t demo:v4 .
·RUN
在容器中运行命令并创建新的镜像层,常用于安装软件包:
RUN yum install-y vim
我们编辑dockerfile
[root@serverl docker]# docker build -t demo:v5 .
虽然我们没有指定file1和file2的路径但是我们使用WORKDIR,他就会相当于我们使用了cd功能默认后面的操作都在workdir中的目录中
·CMD与ENTRYPOINT
这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。
[root@server1 docker]#cat index.html
www.westos。org
[rooteserver1 docker]#1s Dockerfile index.html nginx-1.16.1.tar.gz testfile
[rooteserver1 docker]# docker cp index.html nginx:/usr/share/nginx/html/
我们可以编辑dockerfile
在最后添加上
CMD echo helloworld
[rooteserver1 docker]# docker build -t demo:v6 .
[rooteserver1 docker]# docker run -it --rm demo:v6
helloworld
也可以结合ENV,CMD echo $hostname
[rooteserver1 docker]# docker build -t demo:v7 .
[rooteserver1 docker]# docker run -it --rm demo:v7
server1
如果我们在后面加一个shell他就没有了输出结果
但是如果我们把CMD改成ENTRYPOINT echo $hostname
然后我们去build,docker built -t demo:v8 .然后run ,通过对比发现他不可以覆盖
Shell和exec格式的区别
#cat Dockerfile
FROM busy box
ENV name world
ENTRYPOINT echo"hello,Sname"
Shell格式底层会调用/bin/sh-c来执行命令,可以解析变量,而下面的exec格式不会:
#cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo","hello,$name"]
需要改写成以下形式:
#cat Dockerfile
FROM busybox
ENV name world
ENTRYPOINT [/bin/sh","-c","echo hello,$name"]
Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时
ENTRYPOINT会忽略任何CMD或dockerrun提供的参数。
#cat Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world“]
FROM busybox
ENV hostname server1
WORKDIR /nginx
ADD nginx-1.16.1. tar. gz /nginx
VOLUME ["/data"]
RUN touch filel
RUN touch file2
CMD ["/bin/sh", "-c", "echo $hgstname"]
然后built和run发现这种写法是对的,单纯的CMD ["$hgstname"]存在语法错误
我们在
然后built 和run
[root@serverl docker]# docker run -it --rm demo:v11
hello world
[root@server1 docker]# docker run-it--rm demo:v1l westos
hello westos
[rooteserver1 docker]# docker run-it--rm demo:v11 linux
hello linux
CMD是可以覆盖的
看下在运行容器时的区别:
#docker run--rm busybox:v1
hello world
#docker run--rm busybox:v1 linux
hello linux
官方推荐使用exec格式书写