这是一篇2017年左右的记录, 内容可能已经过时
- Docker的image类似于Git的repo,而docker的tag则类似于git的branch
- 由于内核共享, Docker container 里的uid/gid是和宿主机复用的, 所以相关的鉴权系统也和系统一致.
- 用户名可能不一致, container内可以使用自己的用户名.
- 可以使用
--user
来指定docker container内所有进程的执行身份
- Docker 可以近似为特化的虚拟机,除了Kernel外,所有的其余部分都可以是Docker独占的。
- 例如,可以制作完整的OS镜像,这些OS镜像除了没有内核,其余都和正常的OS是一致的。
- Docker之间的隔离相比VM要浅一些,可能存在一些安全问题;另一方面,VM则由于可攻击面更大,也有安全问题
- Docker可以说是一个Utility, 并没有自创新技术,所以Docker中的技术主体为
Docker-Engine
,它只是驱动整个体系高效的运转. - Docker是通过Kernel的功能实现功能上的"隔离"
- 对于docker内的进程,它认为自己在独立的主机中,且看不到外部的进程
- 对于宿主机,所有docker内的进程都是客观存在的
- Docker使用Linux的Namespace进行隔离,具体包括
- 文件系统: 每个容器都有自己的root文件系统
- 进程隔离: 每个容器都有独立的用户空间
- 网络隔离: 每个容器都在自己独立的子网中,这个子网宿主也不能访问,必须将其内部的端口映射到宿主的端口上才能使用.
- 资源隔离: 每个容器的CPU/内存资源等都是隔离的.
- CoW:根文件系统是写时复制的,不写入新数据的话不会创建文件副本.
- Docker镜像: 可以认为Docker镜像是一个类似于bootable-iso一样的文件系统.
- Docker镜像是只读的,启动后仍然是只读的.
- 文件系统是可以分层叠加的,例如,ubuntu镜像提供了rootfs, 后续的镜像就可以基于rootfs继续添加文件.
- Docker镜像的典型文件系统层为: bootfs-rootfs-user_files
- 镜像启动后变成了container实例,每个实例都有自己的一个可读写层.对镜像内的文件系统IO时,若有写入,会写时复制到可读写层中,之后,该容器只会使用写时复制的版本,镜像内的只读版本仍然存在,但是不会被使用了;换言之,如果不写入数据,读取的永远是镜像内的数据.
- Container实例常可被称为"镜像栈",即启动若干镜像,逐层累积起来,最后再添加一个读写层.
- Docker的标准IO流都会被自动被记录到日志中. 可以用
docker logs container_id
来查询对应的stdout - Docker镜像内可以启动
bash
等,从而看起来像虚拟机一样提供用户接口. - Docker Community Edition
- 直接看Docker-CE Ubuntu即可
- Mac 及 Windows的Docker都是通过中间的一个虚拟机实现的.
- Edge release和Toolbox都是depreciated.
- Docker 内置了和Github类似的DockerHub(官方), 提供类似服务的服务器称为
Registry
- 本地创建的镜像可以通过tag系统和
Registry
映射(相当于 git remote add),docker tag local_image username/reponame:tagname
- 本地创建的镜像可以通过tag系统和
- Docker-Engine为CS架构
- Server: 提供核心服务的daemon
dockerd
,dockerd
自身会暴露出REST API - Client: CLI工具,即
docker
指令,该指令内部通过REST API与dockerd交互. - 因此,WIN/MAC的Docker中,虚拟机中仅安装Server,客户机中仅安装Client.
- Server: 提供核心服务的daemon
- Docker中的常见元素:
- Dockerfile : 相当于编译脚本, 用于生成 Image
- Image : 一个只读镜像, 用于初始化Container
- Container: 实例化的Image, 销毁时会摧毁所有没有
- TODO: 可以在了解Docker之后看Document -> Develop With Docker -> Develop images
Dockerfile
- Dockerfile 相当于一个执行脚本.
- 创建一个
FROM
镜像的实例 - 每一个指令都会对上一步启动的实例进行修改, 并保存为一个新的"中间镜像",再启动这个"中间镜像",作为下一步待修改的实例.换言之,每一条指令都对应了一个"镜像层".(Docker build的日志能很好的体现这个过程)
- Dockerfile中的每一个指令都会产生一个自己对应的缓存,当指令被修改时,只有后续的指令会被重新构建.利用这一特性,可以写一些基础模板dockerfile,build之后作为其他镜像的
FROM
,加速构建过程. - 尽管只有最后一步输出的镜像是有用的,中间镜像也会被缓存,以加速build,这可能导致一些麻烦,可以通过
docker build --no-cache
来禁用中间镜像的缓存,强制从头开始执行. - 一个典型的避免cache的好技巧是在头部添加
ENV MIRROR_REFRESH_DATE xxxx
-
- 这个值可以供容器查询镜像的构建时间.
-
- 修改这行代码会强迫后续的所有指令都不使用缓存.
-
- Dockerfile中的每一个指令都会产生一个自己对应的缓存,当指令被修改时,只有后续的指令会被重新构建.利用这一特性,可以写一些基础模板dockerfile,build之后作为其他镜像的
- 若脚本没有执行完成,那么build的产物是最后成功执行的那个镜像,此时一般可以交互式的启动这个镜像,并在其中进行debug,判断Dockerfile执行失败的原因.
- 创建一个
- 没有
FROM
,或者FROM scratch
的image被称为baseimage - 指令均为大写,例如
FROM
,RUN
DOCKERFILE command
RUN xxx
, 在中间容器实例中执行/bin/sh -c xxx
ENV name value
, 在构建环境及容器实例中创建环境变量,(这个环境变量也可以被DOCKERFILE自身使用)EXPOSE num
, 将num
加入可供映射的网络端口列表,该端口必须在docker run
时进行映射才能使用.CMD [xxx,yyy,zzz]
, 镜像启动默认参数,在镜像被docker run
启动时,若没有给出运行参数,则会自动将xxx yyy zzz
附加到末尾ENTRYPOINT [xxx,yyy,zzz,THE_CMD]
,docker run
输入的THE_CMD
实际会附加到这里被container执行.( 这个特性是可以被指令强制覆盖的)WORKDIR
, 相当于cd
,切换工作目录,最后设置的WORKDIR
将作为ENTRYPOINT
的执行目录USER
, 设定启动用户,默认值为root
VOLUME [path1,path2]
, 创建挂载点及对应的虚拟卷- 虚拟卷是和镜像绑定的,每一个容器实例都会在启动时自动挂载对应的虚拟卷.换言之,镜像的所有实例之间都共享虚拟卷.
- 使用虚拟卷主要是为了在容器中实时的共享文件,相比之下, 在容器中对非虚拟卷的操作都是local的,无法共享出去.(特别的,镜像X可以通过启动
docker run --volume-from y
挂载镜像y虚拟卷) - 如果想把宿主的文件挂载到容器中, 可以在docker run时通过
-v local_path:container_path
创建,-v
可以覆盖容器内的挂载关系(包括虚拟卷)
ADD source dest
, 将宿主机的文件cp到container中,这里源还可以是http://../a.zip
这样的路径. 如果源是tar.gz
等压缩文件,还会被解压.- ADD会强制刷新缓存,执行到ADD之后,后续的指令一定不会使用之前的缓存.
COPY source dest
,行为和ADD类似,但是不会做自动解压的工作.LABEL
,为镜像添加描述信息STOPSIGNAL
,容器停止时像容器内进程发送的信号,即kill
的参数ARG x=yyy
,用户在build
时,可以通过docker build --build-arg x=value
传入参数,如果没有传入,使用yyy
作为默认值,注意,由于所有docker
的调用都会被日志系统明文保存,所以不要传递密码等信息作为参数.ONBUILD DOCKER_CMD
,DOCKER_CMD
会在当前dockerfile以及它的子镜像中被执行,例如,一个镜像中有FROM:xxx
,那么在build时,它会先自动执行xxx
中的ONBUILD
,注意,ONBUILD对孙镜像是无效的.
mmand Sheet
## List Docker CLI commands docker docker container --help
Display Docker version and info
docker –version
docker version
docker info # 主要用于查看 image数和container数
docker stats # 查看所有容器的运行状态
Execute Docker image
注意 image_name后面都可以加`:`指定tag
docker run hello-world # 启动并自动attatch到container内
docker run -i -t
-i 启用container的stdin
-t 为container添加一个虚拟tty,相当于为docker提供一个stdout和stdin,并映射到到host的对应项目.
一般而言,如果需要与容器interactive,这两个选项是必须的.(当然,docker内还需要提供一个cli界面程序连接到tty,如shell)
docker run -e # 添加环境变量
docker run -p # 设定端口映射
docker run -u # 设定启动用户
docker run -d # 启动且不attatch到container内, 相当于后台运行
docker -run –name xxxx # 启动时为container 起一个名字,最好是有一个
docker run 执行的程序在return后容器会自动EXIT,因此,run启动的程序一般必须得是常驻不return的.
docker pull image_name:tag # 拉取指定的image
docker start container_id # 启动一个EXIT状态的container, start 不会自动将终端切入到container中,所以需要 docker attach container_id
docker create xxx # 创建而不启动container
docker exec # docker run参数类似,是在已经启动的容器中执行新的程序
docker stop/kill: container_id # 停止容器
docker rm # 删除容器
List Docker images
docker image ls
List Docker containers (running, all, all in quiet mode)
docker container ls
docker container ls –all
docker container ls -aq
docker build -t friendlyhello . # Create image using this directory's Dockerfile 若没有指定-t,那么会使用latest
docker run -p 4000:80 friendlyhello # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode
docker container ls # List all running containers
docker container ls -a # List all containers, even those not running
docker container stop <hash> # Gracefully stop the specified container
docker container kill <hash> # Force shutdown of the specified container
docker container rm <hash> # Remove specified container from this machine
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag <image> for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry
list container status
docker ps -a
list apps in container
docker top container_id