Docker容器基础
Docker 对象
- 镜像
镜像可以看做是一个根文件系统,包含了操作系统,应用程序所需要的库资源等 - 容器,
在镜像的基础上,加入可读可写层。在容器的所有操作都会写入到最上层的可读可写层,每次删除容器最上层的读写层就会被删掉,所以这期间写入得数据也一并删掉了。如果想深入了解容器的分层原理可以学习下联合文件系统。
docker event state
1_vca4e-SjpzSL5H401p4LCg.pngDockerfile 用法
Dockerfile 是构建镜像的源代码
docker可以自动化的生成镜像通过dockerfile,dockerfile是一个文本文件包含了用户创建镜像需要的所有指令。
常用指令
FROM
- FROM指定一个基础镜像, 一般情况下一个可用的 Dockerfile一定是 FROM 为第一个指令。至于image则可以是任何合理存在的image镜像。
COPY 复制
格式:
- COPY [--chown=<user>:<group>] <源路径>... <目标路径>
- COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。比如:
COPY a* /mydir/
COPY a?.txt /mydir/
目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
ADD 复制
- ADD相比于COPY支持tar文件和url路径。
- tar 是本地文件,将自动展开为目录,类似于解压,如果是url的tar文件则不自动解压
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
- ADD 将文件从路径 <src> 复制添加到容器内部路径 <dest>,dest必须写成dest/。
小结
COPY和ADD 复制目录时有些特殊,对于目录而言:只复制目录中的内容而不包含目录自身
ADD go /usr/local/ 仅仅复制了go目录里的内容没有复制目录
ADD go /usr/local/go/ 复制go目录
官方建议:如果需要解压则用ADD,否则用COPY
WORKDIR
可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
ENV
定义容器的环境变量
格式有两种:
- ENV <key> <value>
- ENV <key1>=<value1> <key2>=<value2>...
ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
在dockerfile 可以通过$变量 调用
RUN
docker build创建镜像时执行一些指令
RUN <command> 由shell启动,Linux默认为/bin/sh -c
, id为1的进程为bin shell,子进程为command
RUN yum install -y wget &&\
mkdir /app
RUN 会增加中间层镜像,考虑到镜像的大小尽量把所以有命令写入到一个RUN命令下
CMD
- shell 格式:CMD <命令>
- exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
CMD /tools/start.sh
命令会自动解释成
CMD [ "sh", "-c", "/tools/start.sh" ]
ENTRYPOINT
- ENTRYPOINT的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。
- 当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
<ENTRYPOINT> "<CMD>"
-
ENTRYPOINT指令和CMD指令虽然是在Dockerfile中定义,但是在构建镜像的时候并不会被执行,只有在执行docker run命令启动容器时才会起作用。
-
ENTRYPOINT 使用场景:
docker run 启动容器时可以指定参数,指定的参数会作为entrypoint命令的参数,而不会覆盖启动命令。
docker 常见命令
-
从当前目录的dockerfile创建容器
docker build -t tagName . -
指定dockerfile 创建容器
docker build -f path . -
删除全部容器
docker rm $(docker ps -aq) -
删除所有镜像
docker rmi $(docker images -q) -
停止运行中的容器
docker stop $(docker ps -q) -
启动一个bash终端,退出自动删除容器
docker run --rm -it imageID /bin/bash -
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
检查本地是否存在指定的镜像,不存在就从公有仓库下载
利用镜像创建并启动一个容器,分配一个文件系统,并在只读的镜像层外面挂载一层可读写层从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
从地址池配置一个 ip 地址给容器,执行用户指定的应用程序
执行完毕后容器被终止 -
更多的时候,需要让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现
-
启动已终止的容器
docker container start -
进入容器
docker exec -it containerID bash
如果从这个 stdin 中 exit,不会导致容器的停止。这就是为什么推荐大家使用 docker exec 的原因. 而不是attach
docker-compose 编排容器
docker compose 用于在单机上编排容器,便于管理多个容器。
version: '3'
services:
web:
image: "ubuntu"
debian:
image: "debian"
上面例子是一个简单的compose.yml文件,web和debian代表了连个容器,image代表镜像。
-docker-compose up -d 会在后台创建容器