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

2018-09-28  本文已影响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是空的。

上一篇下一篇

猜你喜欢

热点阅读