Docker
云服务概念
Docker优点
- 只关心应用:以往我们需要关心操作系统、软件、项目,有了docker我们可以只关心应用而不是操作系统,docker发展迅速,基于docker的paas平台也层出不穷,使得我们能更方便的使用docker
- 快速交付:docker可在秒级提供沙箱环境,开发,测试,运维使用完全相同的环境来部署代码
- 微服务:docker有助于将一个复杂系统分解,让用户用更离散的方式思考服务
- 离线开发:将服务编排在笔记本中移动办公,使用docker可在本机秒级别启动一个本地开发环境
- 降低调试成本:在测试和上线时产生无效的类、有问题的依赖、缺少的配置等问题,docker可让一个问题调试和环境重现变得更简单
- CD:docker让持续交付实现变得更容易,特别是对于蓝绿部署就更简单。
- 第一版上线时,需要上第二版新功能,两个版本功能会有冲突,这时用docker实现蓝绿部署就非常方便了
- 如:可以部署两个版本同时在线,新版本测试没问题了把老版本流量切到新版本就可以了
- 迁移:可以很快的迁移到其他云或服务器
- 与传统虚拟机方式相比,容器化方式在很多场景下都是存在极为明显的优势。无论是开发、测试、运维都应该尽快掌握docker,尽早享受其带来的巨大便利
Docker镜像常用命令
docker image pull
- 下载镜像的命令。镜像从远程镜像仓库服务的仓库中下载。默认情况下,镜像会从 Docker Hub 的仓库中拉取
- 如
docker image pull alpine:latest
命令会从 Docker Hub 的 alpine 仓库中拉取标签为 latest 的镜像
docker image ls
- 列出了本地 Docker 主机上存储的镜像。可以通过 --digests 参数来查看镜像的 SHA256 签名
docker image inspect
- 命令完美展示了镜像的细节,包括镜像层数据和元数据
docker image rm
- 用于删除镜像
docker image rm alpine:latest
命令的含义是删除 alpine:latest 镜像。当镜像存在关联的容器,并且容器处于运行(Up)或者停止(Exited)状态时,不允许删除该镜像
Docker容器常用命令
docker container run
- 启动新容器的命令。该命令的最简形式接收镜像和命令作为参数。镜像用于创建容器,而命令则是希望容器运行的应用
docker container run -it ubuntu /bin/bash
命令会在前台启动一个 Ubuntu 容器,并运行 Bash ShellCtrl-PQ
会断开 Shell 和容器终端之间的链接,并在退出后保持容器在后台处于运行(UP)状态。
- docker container ls
- 用于列出所有在运行(UP)状态的容器。如果使用
-a
标记,还可以看到处于停止(Exited)状态的容器
- 用于列出所有在运行(UP)状态的容器。如果使用
docker container exec
- 用于在运行状态的容器中,启动一个新进程。该命令在将 Docker 主机 Shell 连接到一个运行中容器终端时非常有用
docker container exec -it <container-name or container-id>
bash 命令会在容器内部启动一个 Bash Shell 进程,并连接到该 Shell- 为了使该命令生效,用于创建容器的镜像必须包含 Bash Shell
docker container stop
- 此命令会停止运行中的容器,并将状态置为 Exited(0)
- 该命令通过发送 SIGTERM 信号给容器内 PID 为 1 的进程达到目的
- 如果进程没有在 10s 之内得到清理并停止运行,那么会接着发送 SIGKILL 信号来强制停止该容器
docker container stop
可以接收容器 ID 以及容器名称作为参数
docker container start
- 重启处于停止(Exited)状态的容器。可以在
docker container start
命令中指定容器的名称或者 ID
- 重启处于停止(Exited)状态的容器。可以在
docker container rm
- 删除停止运行的容器。可以通过容器名称或者 ID 来指定要删除的容器。推荐首先使用 docker container stop 命令停止容器,然后使用 docker container rm 来完成删除
docker container inspect
- 显示容器的配置细节和运行时信息。该命令接收容器名称和容器 ID 作为主要参数
Dockerfile
基本概念
- Docker 的核心思想就是如何将应用整合到容器中,并且能在容器中实际运行
- 将应用整合到容器中并且运行起来的这个过程,称为“容器化”(Containerizing),有时也叫作“Docker化”(Dockerizing)。容器是为应用而生的,具体来说,容器能够简化应用的构建、部署和运行过程
- Dockerfile是面向开发的,我们以后要发布项目,就需要编写Dockerfile
- Docker镜像逐渐成为企业交付的标准。以前交付jar或者war包,现在将应用和环境打包成docker镜像交付,打通开发与运维,方便部署
- Dockerfile:构建镜像的文件,定义构建镜像的一切步骤,源代码
- DockerImages:通过Dockerfile构建生成的镜像,最终发布和运行的产品
- Docker容器:容器是镜像的运行时实例,是从镜像中运行起来服务的。正如从虚拟机模板上启动 VM 一样,用户也同样可以从单个镜像上启动一个或多个容器
Dockerfile基本命令
-
Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大
-
FROM
- 定制的镜像都是基于 FROM 的镜像
-
RUN
- 用于执行后面跟着的命令行命令。有以下两种格式
- shell格式
RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。
- exec格式
RUN ["可执行文件", "参数1", "参数2"] # 例如: # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
- shell格式
- 用于执行后面跟着的命令行命令。有以下两种格式
-
COPY
- 复制指令,从上下文目录中复制文件或者目录到容器里指定路径
[–chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组COPY [--chown=<user>:<group>] <源路径1>... <目标路径> COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
- 复制指令,从上下文目录中复制文件或者目录到容器里指定路径
-
ADD
- ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定
- ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
-
CMD
- 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- CMD 在
docker run
时运行 - RUN 是在
docker build
时运行
- CMD 在
- 作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
- 注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 shCMD <shell 命令> CMD ["<可执行文件或命令>","<param1>","<param2>",...] CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
- 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
-
ENTRYPOINT
- 类似于 CMD 指令,但其不会被
docker run
的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序 - 但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序
- 优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数
- 注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
- 类似于 CMD 指令,但其不会被
-
ENV
- 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
ENV <key> <value> ENV <key1>=<value1> <key2>=<value2>...
- 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
-
ARG
- 构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖ARG <参数名>[=<默认值>]
- 构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量
-
VOLUME
- 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷
- 作用:
- 避免重要的数据,因容器重启而丢失,这是非常致命的
- 避免容器不断变大
- 在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点
-
EXPOSE
- 仅仅只是声明端口
- 作用:
- 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
- 在运行时使用随机端口映射时,也就是
docker run -P
时,会自动随机映射 EXPOSE 的端口
EXPOSE <端口1> [<端口2>...]
-
WORKDIR
- 指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)
- docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在
WORKDIR <工作目录路径>
-
USER
- 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)
USER <用户名>[:<用户组>]
- 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)
-
HEALTHCHECK
- 用于指定某个程序或者指令来监控 docker 容器服务的运行状态
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令 HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
- 用于指定某个程序或者指令来监控 docker 容器服务的运行状态
-
ONBUILD
- 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令
ONBUILD <其它指令>
- 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令
例子
- 使用 Docker 中的
docker image build
命令会读取 Dockerfile,并将应用程序容器化 - Dockerfile 由一行行命令语句组成,并支持以 # 开头的注释行。例如:
# Test web-app to use with Pluralsight courses and Docker Deep Dive book # Linux x64 FROM alpine LABEL maintainer="username@xxx.com" # Install Node and NPM RUN apk add --update nodejs nodejs-npm # Copy app to /src COPY . /src WORKDIR /src # Install dependencies RUN npm install EXPOSE 8080 ENTRYPOINT ["node", "./app.js"]
- 使用 -t 参数为镜像打标签,使用 -f 参数指定 Dockerfile 的路径和名称,使用 -f 参数可以指定位于任意路径下的任意名称的 Dockerfile
- 构建上下文是指应用文件存放的位置,可能是本地 Docker 主机上的一个目录或一个远程的 Git 库
- Dockerfile 中的 FROM 指令用于指定要构建的镜像的基础镜像。它通常是 Dockerfile 中的第一条指令
- Dockerfile 中的 RUN 指令用于在镜像中执行命令,这会创建新的镜像层。每个 RUN 指令创建一个新的镜像层
- Dockerfile 中的 COPY 指令用于将文件作为一个新的层添加到镜像中。通常使用 COPY 指令将应用代码赋值到镜像中
- Dockerfile 中的 EXPOSE 指令用于记录应用所使用的网络端口
- Dockerfile 中的 ENTRYPOINT 指令用于指定镜像以容器方式启动后默认运行的程序
- 其他的 Dockerfile 指令还有 LABEL、ENV、ONBUILD、HEALTHCHECK、CMD 等
Docker网络原理
- 每启动一个Docker容器,Docker就会给该Docker容器分配一个ip,只要安装了docker,系统就会有一个网卡docker0
- Linux Docker 创建单机桥接网络采用内置的桥接驱动,而 Windows Docker 创建时使用内置的 NAT 驱动。实际上,这两种驱动工作起来毫无差异
- 宿主机时一个Docker容器的网桥
- 网络模型
SpringBoot微服务打包Docker镜像
-
步骤
- 构建springboot项目
- maven pakage打包应用
- 编写dockerfile
- 构建镜像
- 发布运行
-
示例
# 基础镜像
FROM java:8
# 将当前项目所有jar包打包到app.jar中
COPY *.jar /app.jar
CMD ["--server.port=8080"]
# 暴露端口号
EXPOSE 8080
# 运行应用
ENTRYPOINT ["java", "-jar", "/app.jar"]
Docker Compose
-
Docker Compose 与 Docker Stack 非常类似。它能够在 Docker 节点上,以单引擎模式(Single-Engine Mode)进行多容器应用的部署和管理
-
多数的现代应用通过多个更小的服务互相协同来组成一个完整可用的应用。比如一个简单的示例应用可能由如下 4 个服务组成
- Web前端
- 订单管理
- 品类管理
- 后台数据库
将以上服务组织在一起,就是一个可用的应用
-
部署和管理繁多的服务是困难的。而这正是 Docker Compose 要解决的问题
-
Docker Compose 并不是通过脚本和各种冗长的 docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,从而使用一条命令完成部署
-
应用部署成功后,还可以通过一系列简单的命令实现对其完整声明周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理