技工九三四笔记

技工九三四笔记

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Docker学习笔记

什么是Docker

docker是什么

docker 是一种让容器(container)在主机(host)能运行的一种技术,主要包括容器规范、容器runtime、容器定义/管理工具、Register以及容器OS

docker管理工具

规范:Open Container Initiative(OCI)发布了两个规范:runtime spec和image for mat spec。保证在不同镜像可以在不同的runtime上面正常运行。

runtime: 容器的运行环境,主流的包括runc、lxc、rkt,其中runc是Docker自己开发的。

容器管理工具:runc对应的是docker engine,其中包括了 deamon和cli;lxc对应的是lxd;rkt对应的是rkt cli。

容器定义工具:docker image是Docker容器的模板,dockerfile是包含若干命令的文本文件,ACI(App Container Image)与docker image类似,但是是centos开发的。

Registry: Registry保管镜像就有点像git来管理代码。Docker Hub是Docker的官方Registry,Quay.io是另一个。当然也可以利用Docker Registry自建。

容器OS:专门运行容器的系统,优势是比其他系统更小,比如CoreOS、Atomic和Ubuntu Core。

  1. docker与虚拟机的区别

docker是基于主机Host的系统内核,所以更加轻便,而虚拟机则是完全模拟出一个系统环境,更粗暴的理解从系统层面来看,虚拟机就是一个完全独立的“国家”,而docker环境就有点像半殖民地的样子。

docker镜像

镜像结构

镜像层次可以分为核心层(kernal)、镜像层和容器层(其中容器层是可写入的状态)。docker有个重要的特性就是:Copy-on-Write,也就是变更出现只会出现在容器层,不会变更到镜像层。在容器层面添加文件,文件只会保留在容器层;读取是在从上到下层读,直到读取文件写入内存;修改文件:从镜像层查找到文件后复制到容器层,然后修改;删除也不是直接删掉镜像里面的文件,而是在容器层记录这个删除动作而已。

构建方式

docker构建方式分两种,一种是从已经在运行的容器中打包(commit)成镜像,一种是通过Dockerfile来实现。

  1. commit
docker commit [容器名] [新镜像名]
  1. build

build是借助Dockerfile来完成构造:.表示build context,我们可以用-f来表明dockerfile所在位置,不然就会默认在build context找。其本质就是每执行一条指令,生成一个容器然后commit成新的镜像层。

docker build -t [镜像名] .

缓存特性:

docker镜像生成是一层层叠加的,为了提升生成速度,docker会缓存已有镜像的镜像层,构建新镜像时,如果镜像已经存在就会直接使用,无须重新创建。如果不希望使用缓存,可以使用--no-cache参数。Dockerfile中每一个指令都会创建一个镜像层,上层是依赖下层的,所以如果上面的语句发生变化,那么下面的缓存都会失败。

  1. Dockerfile

docker的Dockerfile常用指令:

  • FROM:指定默认镜像,每个Dockerfile必须包含的指令,如果确实没有默认的镜像可以用scratch
  • MAINTAINER:设置镜像作者,可以任意字符串
  • COPY:将文件从build contxtx复制到镜像
  • ADD:与COPY类似,但是它会自动解压压缩文件(tar\zip\tgx\xz等)
  • ENV:设置环境变量
  • EXPOSE:指定容器监听某个端口,Docker可以将该端口暴露出来。
  • VOLUME:将文件或目录声明为volume,把目录下文件打包进镜像。
  • WORKDIR:切换当前工作目录,为RUN\CMD\ENTRYPOINT\ADD或者COPY使用。
  • RUN:在容器指令命令
  • CMD:容器启动且docker没有指定其他运行指令,只最后一个生效
  • ENTRYPOINT:容器启动时运行的命令,但是只有最后一个生效,CMD或者run 之后的参数会被当成参数传递给ENTRYPOINT。

三、RUN/CMD/ENTRYPOINT区别

在docker有两种命令运行方式:shell和exec。

shell格式:<instruction><command>run apt-get install python,通常run使用这种格式

exec:<instruction>["executable", "param1", "param2"]run ["apt-get", "install", "python"]。通常CMD和ENTRYPOINT推荐这种格式。

但是要注意一点,指令执行时,会直接调用[COMMAND],不会进行shell解析。比如ENV name Docker ENTRYPOINT ["/bin/echo", "Hello, $name"],name是不会被替换的,你需要改成ENV name Docker ENTRYPOINT ["/bin/sh", "-c","echo Hello, $name"]

指令 多个指令是否会被覆盖 格式 推荐使用场景
run exec和cmd都支持 构建镜像安装应用鹅软件包
CMD 除了支持exec和cmd,还支持cmd ['param1', 'param2']格式来给ENTRYPOINT传参,但是ENTRYPOINT必须使用exec格式。通用我们运行run -it时候后面参数就是这样传递。 容器默认启动命令,可以使用CMD
ENTRYPOINT exec和cmd都支持,但是如果使用CMD传参就必须用exec格式。
ENTRYPOINT ['"bin/echo","hello" ] CMD ["world"]
docker运用程序或服务,如运行一个Mysql,可以优先使用exec格式,用CMD传参,后面可以被run命令替换
  1. 管理镜像

特定镜像的名字由两部分组成:[repository]:[tag]。如果在build时候没有加tag,那么默认latest。可以通过docker tage [镜像名] [新镜像名]来打tag。

如果要上传自己的镜像到docker hub,镜像中的repository包含,格式如下 :registry:[username]/xxx:tag,接着使用docker push就可以推送。

docker窗口

容器的创建运行

运行指令:docker run -it [镜像名] [command] -it 表示终端交互,-d后端运行, --name显示给容器命名, --restart=always总是表示自动重启,也可以填非零整数,表示最多重启次数。

容器的相关操作

  • 进入容器:有两种方式,一种是通过docker attach,一个是通过docker exec 后面跟容器短ID\长ID或者容器名字。attach是不会启动新的进程,但是exec是打开新的终端,如果想看启动命令就需要用attach,也可以用docker logs。attach 可通过Ctrl+p然后加Ctrl+q组合退出attach终端,在exec退出用exit。
  • 查询运行容器:docker ps
  • 停止容器:docker stop [containerID] docker stop其实是向进程发送一个SIGTERM信号,如果想快速,可以使用docker kill命令。
  • 启动容器:docker start [containerID],启动之前停止的容器
  • 重启容器:docker restart [containerID],相当于先stop再start。
  • 暂停容器:docker pause [containerID]
  • 恢复容器:docker unpause [containerID]
  • 删除容器:docker rm [containerID],rm可以一次性删除多个

容器资源限制:

对于容器,Docker也提供类似资源限制参数

  • 内存: -m或者--memory是直接限制内存,--memory-swap为内存+swap限制
  • 处理器:-c或者--cpu-shares设置权重,这里要注意的是,这里的值不代表绝对数量,只是一个权重值。
  • BlockIO带宽限额:BlockIO指磁盘的读写,可以通过权重、限制bps和iops的方式控制容器读写带宽。--blkio-weight改变容器block IO优先级,默认500。也可以直接限制读写速度:--device-read/write-bps/iops

Docker网络

在创建容器时,有个参数network来管理docker的网络配置。

None网络

如果在创建中直接使用了--network=none,表示完全封闭的网络,这种对于需要高安全性且不需要联网的服务有用。

Host网络

如果在创建中直接使用了--network=host,表示使用host网络,直接使用host的网络好处是如果窗口对网络传输效率有较高要求的话,性能会比较好,但是可能就会出现端口冲突问题了。

Bridge网络

bridge是network默认选项,用的是veth pair技术,类似用一根虚拟网络连接一对网卡,网卡一头连容器,一头连网桥。

自定义user-defined网络

用户可以自定义网络,三种网络驱动包括:bridge、overlay和macvlan。创建方法是先用docker network 创建:docker network create --driver [driver name] [network name],然后在network参数直接用新建的就可以。

容器通信

容器间想要通信有以下几种方式:

  1. IP通信,在一个网络的网卡就可以
  2. Docker DNS Server:仅限user-defined有效。
  3. joined容器,第二个想跟第一个容器通信的话,可以在network=container:[containername]

容器默认可以与外界通讯的原因是因为MASQUERADE通过用户NAT网络地址转换来做了一层处理。而外部访问容器则是使用docerk-proxy。

Docker存储

正是docker storage driver实现了多层数据的堆叠并为用户提供了一个单一合并视图。

Data Volume

docker volume本质是Docker Host文件系统中的目录或者文件,能够直接被挂在容器的文件系统中。data volume是目录或者文件,容器可以直接读写里面的数据,而容器被删它也存在。

docker提供两种类型的volumen: bind mount和docker managed volume。

bind mount是在运行容器时-v <host path>:<container path>:<权限>

docker manage volume与bind mount使用不同的点是不需要指明挂在容器的哪个位置,-v <host path>,因为容器申请时会在/var/lib/docker/volumes下生成一个目录,可以通过docker inspect containerID 或者 docker volume查找(后续可以使用docker volume rm 来删除)。需要注意的是,使用这种方式会把host的文件传到volume。

volumn container

多容器共享数据的问题,一种简单的方式就是都用bind mount的方式绑定同一个目录,但是这个很麻烦,所以提供了volumn container的方法:

  1. 首先创建一个容器:docker create --name vc_data -V [hostpath]:[containerpath] -v <hostpath> [image]
  2. 在其他容器启动时加 --volumes-from vc_data 就可以了。

实战

搭建一个自己Python的Jupyter notebook环境:

获得PIP安装包:

pip freeze > requirements.txt

Dockerfile:

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

运行build:

docker build -t jupyternotebook-934 .

执行:

docker run -it -rm -p 8888:8888 \
  jupyternotebook-934 \
  jupyter notebook \
  --ip=0.0.0.0 --port=8888 --no-browser \
  --allow-root
posted on 2025-12-14 16:01  技工九三四  阅读(7)  评论(0)    收藏  举报