美文网首页
docker3--基础学习(重新认识docker)

docker3--基础学习(重新认识docker)

作者: 一个热爱生活的好少年 | 来源:发表于2018-09-28 16:33 被阅读0次

    之前我们通过了Namespace,Cgroup,rootfs文件系统去学习的容器原理。
    通过例子进行学习:

    from flask import Flask
    import socket
    import os
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        html = "<h3>Hello {name}!</h3>" \
               "<b>Hostname:</b> {hostname}<br/>"           
        return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
        
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=80)
    
    
    
    $ cat requirements.txt
    Flask
    

    先编写一个dockerfile用于制作rootfs

    # 使用官方提供的 Python 开发镜像作为基础镜像
    FROM python:2.7-slim
    
    # 将工作目录切换为 /app
    WORKDIR /app
    
    # 将当前目录下的所有内容复制到 /app 下
    ADD . /app
    
    # 使用 pip 命令安装这个应用所需要的依赖
    RUN pip install --trusted-host pypi.python.org -r requirements.txt
    
    # 允许外界访问容器的 80 端口
    EXPOSE 80
    
    # 设置环境变量
    ENV NAME World
    
    # 设置容器进程为:python app.py,即:这个 Python 应用的启动命令
    CMD ["python", "app.py"]
    

    CMD内容就是entrypoint的参数,且就是容器的启动进程。
    Dckerfile并且是全是对容器内部操作,例如ADD,当前目录复制到容器目录之中。

    关于写完的路径


    image.png

    1.制作docker镜像 -t 起名字:这个命令等于起一个容器执行Dockerfile文件。

    docker build -t helloworld .
    

    在Dockerfile中每个原句执行后,都会生成一个对应的镜像层,即使原语句本身并无明显修改文件操作,例如env语句,也会生成。在外界看来这个层为空的。

    2.关于docker 命令的使用
    查看构建结果

    docker image is
    

    下面是查看机器商的镜像。

    image.png

    启动镜像 :映射docke80端口到宿主机4000

    docker run -p 4000:80 helloworld python app.py
    
    $ curl http://localhost:4000
    <h3>Hello World!</h3><b>Hostname:</b> 4ddf4638572d<br/>
    

    查看当前运行的镜像

    docker ps
    
    image.png

    docker commit指令:把正在运行的程序直接提交为一个镜像。就是把我们在运行的容器所做的操作也保存在镜像之中。

    $ docker exec -it 4ddf4638572d /bin/sh
    # 在容器内部新建了一个文件
    root@4ddf4638572d:/app# touch test.txt
    root@4ddf4638572d:/app# exit
    
    # 将这个新建的文件提交到镜像中保存
    $ docker commit 4ddf4638572d geektime/helloworld:v2
    

    docker exec指令:进入容器之中:本身docker的Namespace的信息在宿主机是以文件的形式存在的。
    获取docker的id,并获取容器pid


    image.png image.png

    我们可以看到真实的Namespace文件。 如果我们可以加入到这个linux Namespace文件中是否可以进入该容器中呢?
    该操作依赖于一个系统调用:通过open()打开文件把描述符fd交给setns()使用,执行后当前进程就加入了该Namespace。 相当于当前执行的进程与容器进程共享一个Namespace。

    docker 提供了参数可以让你启动一个容器加入到另一个容器的Namespace中 -net
    $ docker run -it --net container:4ddf4638572d busybox ifconfig

    以上就是关于docker exec的原理。
    而docker commit :就是把可读写层加上原来的容器镜像的只读层打包一个新的镜像。只读层在宿主机上是共享的不会占用额外的空间。由于使用的联合文件系统,对rootfs的任何修改,都会复制到可读写层上进行修改:Copy-on-Write


    image.png

    图中lnit层存在,可以防止在conmmit时候,把docker自己对/etc/hosts的修改也一起提交掉。

    Volume(技术卷):
    一个机器上完全隔离开的文件系统环境由1.rootfs机制+2.Mount Namespace构建的。
    而容器内外的文件/目录挂载就需要Volume了。它允许宿主机上指定目录或者文件挂载到容器中进行修改与读取。

    两种声明方式:
    docker run -v /test ...
    docker run -v /home:/test ...

    第一种没有写明确的目录:会自动创建 /var/lib/docker/volumes/【volume_id】/_data
    在容器内部修改后外部也会进行变化。


    image.png

    这里使用的挂载技术就是bind mount机制,可以将一个文件或者目录挂载到另一个目录。(不是整个设备)原挂载点将会被隐藏起来,而不受影响。


    image.png

    如图就是inode重定向。
    注意:在commit的时候

    docker commit是发生在宿主机空间的,由于Mount Namespce的隔离作用
    ,它并不知道这个绑定挂载的存在只能看到有个test的空目录。同理,我们在宿主机上去看这个docker的读写层可以看到这个test是空的。

    相关文章

      网友评论

          本文标题:docker3--基础学习(重新认识docker)

          本文链接:https://www.haomeiwen.com/subject/oogjoftx.html