第一板块:docker的一些基本操作指令
docker常用命令参考
docker pull 拉取镜像
docker run 启动容器
docker run -it 容器id 以交互式运行容器
docker run -d 容器id 后台运行容器
docker run -it -name 名称 为容器命名
docker run -it --rm 容器id 容器运行结束后,自动删除容器
docker ps 查看正在运行的容器
docker ps -a 查看全部容器信息(包括已停止的容器)
docker start 容器id 启动停止状态的容器
docker stop 容器id 停止运行中的容器
docker rm 容器id 删除容器
docker images 查看本地镜像信息
docker rmi 镜像id 删除本地镜像
docker inspect 镜像id 查看镜像分层信息
docker version 查看docker版本信息
docker info 查看docker使用信息
第二板块 dockerfile
dockerfile常用参数
参数 参数含义
FROM 拉取基础镜像
CMD 构建完成时执行的指令
RUN 构建时执行的shell命令
ARG 镜像层的环境变量
EVN 镜像层和容器层的环境变量
COPY 拷贝文件
ADD 拷贝文件、URL、压缩文件等
EXPOSE 暴露容器内部的端口给外部使用
dockerfile是一个纯文本,里面记录了一系列的构建指令。比如选择基础镜像、拷贝文件、运行脚本等等,每个指令都会生成一个layer,而docker顺序执行这个文件里的所有步骤,最后就会生成一个新的镜像出来。
简单dockerfile实例说明
# Dockerfiel.busybox
FROM busybox 选择基础镜像
CMD echo "hello world" 启动容器时默认运行的命令
上述文件只里有两条指令,第一条指令是FROM,所有的dockerfile都要从它开始,表示选择构建使用的基础镜像,这里使用的是busybox。
第二条是CMD,它指定docker run启动容器时默认运行的命令,这里使用了echo命令,输出“hello world”字符串。
这里使用docker build 命令来创建出镜像:
docker build -f Dockerfile.busybox .
需要注意命令的格式,这里使用了-f参数指定dockerfile的文件名,后面必须跟一个文件路径,叫做“构建上下文”(build’s context),这里只是一个简单的点号,表示当前路径的意思。
接下来,就会看到docker会逐行的读取并执行dockerfile里的指令,依次创建镜像层,在生成完整的镜像。
这种方式构建出来的镜像是没有名称的,可以添加 -t 参数指定镜像的标签,名称必须符合规则,用 : 分隔名字和标签,若不提供标签,默认就是latest。
需要了解的是只有RUN、ADD、COPY 会生成镜像层,其他指令会生成临时的镜像层。
所以dockerfile里的指令要精简合并,否则太多的层会导致镜像臃肿不堪。
怎样编写正确、高效的dockerfile
因为构建镜像的第一条指令必须是 FROM ,所以基础镜像的选择尤为重要,如果关注的是镜像的安全和大小,那么一般会选择alpine,如果关注的是应用的运行稳定性,那么可能会选择ubuntu、centos等。
我们在本机测试时上开发测试时,会产生一些源码、配置等文件,需要打包进镜像里,这时可以使用 COPY 命令,用法和linux系统的cp差不多,不过拷贝的源文件必须是“构建上下文”路径里的,不能随意指定文件。
COPY 命令示例:
COPY ./a.txt /tmp/a.txt #把构建上下文里的a.txt拷贝到镜像的/tmp目录下。
COPY /etc/hosts /tmp #执行报错,不能使用构建上下文路径之外的文件拷贝。
当上传的目录下文件较多(有部分文件不需要进行拷贝时)也会导致构建效率较低,为了解决这个问题,可以在构建上下文的目录里创建一个 .dockerignore 文件,排除那些不需要的文件。
下面是一个简单的示例,表示不打包上传后缀为swp、sh的文件。
# docker ignore
*.swp
*.sh
接下来要学习的时dockerfile中的 RUN 指令,它可以执行任意的shell命令,比如更新系统、安装应用、下载文件、创建目录等,实现任意的镜像构建步骤,非常灵活。
RUN 通常是dockerfile里最复杂的指令,会包含很多shell命令,dockerfile里的一条指令只能是一行,所有有的 RUN 指令会在每行的末尾使用续航符 \ ,命令之间也会用 && 来连接,这样会保证在逻辑上是一行,就像下面这样:
RUN apt-get update \
&& apt-get install -y \
build-essential \
curl \
make \
unzip \
&& cd /tmp \
&& curl -fSL xxx.tar.gz -o xxx.tar.gz \
&& tar xzf xxx.tar.gz \
&& cd *** \
&& ./config \
&& make \
&& make install
这种超长的指令写起来不美观,同时出错也不易排查,所以会用到变通的技巧,把这些shell命令集中写入到一个脚本里,用 COPY 命令拷贝进去在使用RUN来执行。
COPY set.sh /tmp/
RUN cd /tmp && chmod +x set.sh \
&& ./set.sh \
&& rm set.py
接下来我们需要了解dockerfile里的变量,这里需要使用 ARG 和 ENV 。
它们的却别是 ARG 创建的变量只在镜像构建中可见,容器运行时不可见,而 ENV 创建的变量,不仅能够在构建镜像的过程中使用,在容器运行时也能够以环境变量的形式被应用程序使用。
下面是一个简单的例子,使用了 ARG 定义了基础镜像的名字(可以用在“FROM”指令里),使用 EVN 定义了两个环境变量。
ARG IMAGE_BASE="node"
ARG IMAGE_TAG="alpine"
EVN PATH==$PATH:/tmp
EVN DEBUG=OFF
还有一个重要的指令是 EXPOSE ,它的作用是声明容器对外服务的端口号,对现在基于node.js、tomcat、nginx等开发的微服务系统来说非常有用:
EXPOSR 443 #默认是tcp协议
EXPOSE 53/udp #指定udp协议
完整示例
# dockerfile
# docker build -t ngx-app .
# docker build -t ngx-app:1.0 .
ARG IMAGE_BASE="nginx"
ARG IMAGE_TAG="1.21-alpine"
FROM ${IMAGE_BASE}:${IMAGE_TAG}
COPY ./default.conf /etc/nginx/conf.d/
RUN cd /usr/share/nginx/html \
&& echo "hello nginx" > a.txt
EXPOSE 8081 8082 8083