docker

68 阅读8分钟

三大概念

容器(Container)

容器是应用程序层的抽象,可以将代码和依赖项打包在一起。容器不虚拟化整个物理机,仅虚拟化主机操作系统。

镜像(Image)

镜像是分层的自包含文件,充当创建容器的模板。它们就像容器的冻结只读副本,可以通过仓库进行共享。

仓库(Registry)

一个集中式的位置,可以在其中上传镜像,也可以下载其他人创建的镜像。Docker Hub是Docker的默认公共仓库,MICR就是小米的一个镜像仓库

Docker架构

Docker引擎包括三个主要组件:

  1. Docker守护程序:守护程序是一个始终在后台运行并等待来自客户端的命令的进程,守护程序能够管理各种Docker对象。
  2. Docker客户端:客户端是一个命令行界面程序,主要负责传输用户发出的命令。
  3. REST API:REST API充当守护程序和客户端之间的桥梁,使用客户端发出的任何命令都将通过API传递,最终到达守护程序。

“ Docker 使用客户端-服务器体系结构。Docker client 与 Docker daemon 对话,daemon 繁重地构建、运行和分发 Docker 容器”。

作为用户,通常使用客户端组件执行命令。然后,客户端使用 REST API 来访问长期运行的守护程序并完成工作。

容器的操作命令

查看当前正在运行或过去运行的所有容器

docker ps -a

运行容器

docker run <image name>

docker container run <image name>
公开端口 :--publish 或 -p

容器是隔离的环境,要允许从容器外部访问运行在容器内部的应用程序,必须将容器内的相应端口发布到本地网络上的端口

--publish <host port>:<container port>

分离模式:--detach 或-d

默认情况下,必须将终端窗口保存打开状态来使容器继续运行,关闭终端窗口会停止正在运行的容器。为了覆盖此行为并保持容器在后台运行,可以使用--detach

docker container run --detach --publish 8080:80 fhsinchy/hello-dock

这意味着发送到主机系统端口8080的任何请求都将转发到容器内的端口80

停止后立即被移除:--rm

该参数也可用在container start命令中

docker container run --rm --detach --publish 8888:80 --name hello-dock-volatile fhsinchy/hello-dock
命名:--name

默认情况下,容器有两个标识符:

CONTAINER ID:一个64个字符的随机字符串

NAME:两个随机词的组合,下划线连接

可以使用--name选项来命名容器

docker container run --detach --publish 8888:80 --name hello-dock-container fhsinchy/hello-dock

列表展示容器

docker container ls

重命名容器

docker rename <old name> <new name>

停止或杀死运行中的容器

docker container stop <container identifier>

其中,container identifier可以使容器的ID或名称。

如果使用 name 作为标识符,则 name 将作为输出返回。stop 命令通过发送信号SIGTERM 来正常关闭容器。如果容器在一定时间内没有停止运行,则会发出 SIGKILL 信号,该信号会立即关闭容器。

如果要发送 SIGKILL 信号而不是 SIGTERM 信号,则可以改用 docker container stop <container identifier> 命令

重新启动已停止或终止的容器

docker container start <container identifier>

重新启动正在运行的容器

docker container restart <container identifier>

创建而不运行容器

docker container create <image name>

因此,docker container run实际上是container createcontainer start两个命令的组合

移除挂起的容器

已被停止或终止的容器仍保留在系统中可以使用container rm命令删除停止的容器

docker container rm <container identifier>

也可以使用container prune命令来一次性删除所有挂起的容器

在容器里执行命令

docker container run <image name> <command>

container run命令中,镜像名称后传递的任何内容都将传递到镜像的默认入口里。入口点就是通往镜像的网关。除可执行镜像外的大多数镜像使用shell或sh作为默认入口点,因此,任何有效的shell命令都可以作为参数传递给它们。

注:可执行镜像的入口点设置为自定义程序。

绑定挂载 :--volume 或 -v

是一种授予容器直接访问本地文件系统的一种方法。

绑定挂载可以在本地文件系统目录(源)与容器内另一目录(目标)之间形成双向数据绑定。这样,在目标目录中进行的任何更改都将在源目录上生效,反之亦然。

--volume <local file system directory absolute path>:<container file system directory absolute path>:<read write access>

第三个字段是可选的,但必须传递本地目录的绝对路径和容器内目录的绝对路径。

--volume-v 选项对 container run 以及 container create 命令均有效

Dockerfile文件

Dockerfile是指定的集合,该指令会被守护进程生成镜像。

示例:

FROM ubuntu:latest

EXPOSE 80

RUN apt-get && \
    apt-get install nginx -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

CMD ["nginx", "-g", "daemon off;"]

镜像是一个多层文件,在Dockfile文件中,编写的每一行都将为镜像创建一个层。

  • 每个有效的Dockerfile均以FROM指令开头,该指令为生成的镜像设置基本镜像。此处将ubuntu:latest设置为基本镜像,因此在自定义镜像中可以使用ubuntu的所有功能,比如下面使用apt-get命令安装软件包。
  • EXPOSE指定表示需要发布的端口。
  • RUN指令在shell内部执行命令。apt-get clean && rm -rf /var/lib/apt/lists/*用于清楚程序包缓存,因为不希望镜像中出现任何不必要的文件。
  • CMD指定为镜像设置了默认命令。这里,nginx是指 NGINX 可执行文件。 -gdaemon off是 NGINX 的选项。

.dockerignore文件

类似于.gitignore,用来排除不需要上传到 docker 容器的文件或目录

镜像的操作命令

使用Dockerfile构建镜像

docker image build .

docker image build --file <docker filename> .
  • docker image build 是用于构建镜像的命令。守护程序在上下文中找到任何名为 Dockerfile 的文件。
  • 最后的 . 设置了此构建的上下文。上下文是指在构建过程中守护程序可以访问的目录。

现在要使用此镜像运行容器,可以将 container run 命令与在构建过程中收到的镜像 ID 结合使用。

标记docker镜像

不使用随机生成的ID,为镜像分配自定义标识符

--tag <image repository>:<image tag>

repository 通常指镜像名称,而 tag 指特定的构建或版本。

例如:docker image build --tag custom-nginx:packaged .

列表展示镜像

docker image ls

删除镜像

docker image rm <image identifier>

还可以使用image prune 命令来清除所有未标记的挂起的镜像

可视化镜像的分层

docker image history <image identifier>

镜像的每一层都会占据内存,如果需要删除某些文件,最好在一次RUN中使用后就删除,不要单独使用一次RUN命令来做删除操作

案例分析

开发模式,用npm run server命令启动一个开发服务器,该服务器将应用程序提供给用户

FROM node:lts-alpine   #使用node:lts-alpine作为基础镜像

EXPOSE 80    # 表示要发布的端口为80,但是运行容器时仍需要--publish选项

USER node    # node镜像会附带一个名为node的非root用户,USER命令将镜像的默认用户设置为node

RUN mkdir /home/node/vue-app    # 创建目录

WORKDIR /home/node/vue-app    # 设置工作目录,默认情况下,任何镜像的工作目录都是根目录

COPY ./package.json .   # 将主机文件系统当前目录下的package.json复制到镜像的工作目录中

RUN npm install   # 基于package.json安装依赖

COPY . .       # 将当前目录下的文件全部复制到镜像中

CMD ["npm", "run", "dev"]  # 设置了镜像的默认命令

但是,在生产环境下,npm run build命令将所有JavaScript代码编译为一些静态HTML、CSS和JavaScript文件。要运行这些文件,不需要node或任何其他运行时依赖项,只需要一个像nginx这样的服务器。

让应用程序以生产模式运行时创建镜像,可以执行以下步骤:

  • 使用node作为基础镜像并构建应用程序
  • 在node镜像中安装nginx并使用它来提供静态文件
# 方式1: 在容器中安装软件包再npm run build

FROM node:lts-alpine as builder   #使用node:lts-alpine作为基础镜像开始构建的第一阶段

RUN mkdir /home/node/vue-app  

WORKDIR /home/node/vue-app    

COPY ./package.json .     

RUN npm install 

COPY . . 

RUN npm run build   # 在镜像中编译项目

FROM nginx:stable-alpine  #使用nginx:stable-alpine作为基础镜像开始构建的第二阶段

EXPOSE 80  # 暴露接口为80

# --from=builder表示要从builder阶段复制一些文件。这里的/usr/share/nginx/html 是nginx的默认站点路径,因此放置在其中的任何静态文件都将自动提供

COPY --from=builder /home/node/vue-app/dist /usr/share/nginx/html  

除了在镜像中编译代码,还可以在本地npm run build后,将编译好的产物放在镜像中

# 方式2:直接将构建产物复制到容器里

FROM nginx:stable-alpine

EXPOSE 80

RUN mkdir /app

WORKDIR /app

# 或者COPY ./dist/* /usr/share/nginx/html/

COPY ./dist /usr/share/nginx/html

docker运行nginx

nginx服务器静态资源目录:/usr/share/nginx/html

nginx配置文件目录:/etc/nginx/nginx.conf

nginx log目录:/var/log/nginx