Docker笔记

Published on

是什么

Docker 是一个开源的应用容器引擎,基于 Golang 语言开发,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 服务器。容器是一个沙箱机制、相互隔离、相互之间不会有影响(类似于我们手机上运行的 App),并且容器开销是较低的。

作用

  • 容器化,将应用及其所有依赖项打包在容器中,以便在任何环境运行
  • 一致的运行环境,环境隔离。遇到的问题:本地/测试/线上 运行环境不一致,导致开发发布流程长,成本高。
  • 资源效率,多容器基于操作系统,启动快速且占用资源少,相比虚拟机更轻量
  • 结合 CI/CD 持续集成部署
  • 微服务架构

对比带独立运行环境的虚拟机

  • 打包:就是把你软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包
  • 分发:你可以把你打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装
  • 部署:拿着“安装包”就可以一个命令运行起来你的应用,自动模拟出一样的运行环境,不管是在 Windows/Mac/Linux 自己在本地机器上开发、测试 --> 打包为 Docker 镜像(可以理解为软件安装包) --> 各种服务器上只需要一个命令部署好 核心概念
  • Image 镜像: 一个包含有文件系统的面向 Docker 引擎的只读模板,装了一些系统的配置文件, 可以通过镜像建立容器。容器启动的“原料”。
  • Container 容器:基于镜像创建的,相互隔离的执行单元。类比于“小型虚拟机”
  • Registry 仓库:存放镜像的仓库

主要命令

  • docker version
  • sudo systemctl start docker 启动服务

镜像

  • docker images // docker image ls 列出本机 image
  • docker image rm helloworld 删除本地镜像 helloworld
  • docker image build -t imageName path 构建 image 镜像
  • docker pull 拉取镜像, 默认地址地址 Docker Hub. https://hub.docker.com/explore

容器

  • docker container run helloworld 容器运行 hello world
    • docker container run -p 3000:80 node-red 容器启动 80 端口转到本机的 3000 端口
    • docker container run --rm -p 3000:80 node-red
      • --rm 在容器终止运行后自动删除容器文件
      • --name containerName 指定容器名字
      • -d 在后台运行,不占用终端
  • docker container start containerID run 会每次新建一个容器,start 会启动一个已经存在的容器
  • docker container ls //
    • docker ps 列出正在运行的容器
    • docker ps -a 列出所有容器,包括不在运行的
  • docker container kill [containID] 终止容器
  • docker container rm [containerID] 删除容器
  • docker container logs [containerID] docker 容器 log, 即容器里面 Shell 的标准输出
  • docker container cp [containID]:[/path/to/file] .
    • docker container cp e168f39fd043:/app/package.json .

命令中 image 和 container 可以省略掉。

DockerFile 创建镜像

根据 DockerFile 文件, docker image build 创建 docker image build -t node-red:tag .

  • -t 指定镜像名称和标签
  • -f 指定 Dockerfile

DockerFile

  • FROM node:18.17.0-alpine as builder

    • 该 image 文件继承官方的 node image,冒号表示标签,这里标签是 18.7.0,即 18.7.0 版本的 node。(Alpine 操作系统是一个面向安全的轻型 Linux 发行版, 对比不带 -alpine 版本,Alpine 版本镜像更小,更轻量)
    • as builder 多阶段构建,可以将前面阶段的构建产物复制到当前目录
      • docker ignore FROM node:14 AS builder ... FROM node:14 AS production ... COPY --from=builder /app/dist ./dist
    • 多阶段构建优化
  • WORKDIR /app 设置工作目录为 /app。后续的命令都将在这个目录中执行。如果目录不存在,Docker 会自动创建它。

  • COPY . /app/ 将当前目录下的所有文件复制到 /app 目录下。

  • RUN apk update && apk add git 更新包,安装 git (如有 git 依赖)

  • RUN npm install /app 目录下执行 npm install 安装依赖 RUN 命令写法:

    • RUN /bin/bash -c 'source HOME/.bashrc;echoHOME/.bashrc; echo HOME
    • RUN ["/bin/bash", "-c", "echo hello"]
  • RUN npm run build

  • EXPOSE 80 443 3000 容器暴露端口

  • CMD ["npm", "start"] CMD 容器启动要运行的命令。RUN 是 image 文件的构建阶段执行,执行结果都会打包进入 image 文件。CMD 命令则是在容器启动后执行。一个 Dockerfile 可以包含多个 RUN 命令,但是只能有一个 CMD 命令。 其他部分指令:

  • ENV 设置环境变量

    • ENV <key> <value> 容器中运行的程序都可以使用
  • ARGS ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量,在将来容器运行时是不会存在这些环境变量的。

  • USER 指定后续调用用户(组)

根据 Dockerfile 存在后, docker image build -t imageName path 构建 image. 如:docker image build -t node-red .
-t 指定名称, . 指定当前目录 (目录需要包含 DockerFile)

发布 image

发布流程类比于 npm 发包,登录后将镜像上传至镜像仓库

docker login docker image tag [imageName] [username]/[repository]:[tag] docker image push [username]/[repository]:[tag]

数据管理

对容器中的数据持久化管理以及多容器共享数据

数据卷

数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。 volmue 创建在宿主机,Linux 文件系统,可以多个容器共享 创建数据卷

  • docker volume create my-vol 创建数据卷
  • docker volume ls 列出数据卷
  • docker volume inspect my-vol 查看指定数据卷
  • docker volume prune 清理无 container 引用的数据卷
  • docker rm -v 删除

docker run -v volumeName:/path imageName

对比: docker run -p 9000:9000 hello_val docker run -p 9000:9000 -v my-vol:/app hello_vol curl -X POST -d "New data entry" http://localhost:9000

挂载主机目录

通过路径挂载目录,主机目录修改代码和数据在容器中实时生效 docker run -p 9000:9000 -v /path/to/host/directory:/app hello-node-app

  • docker run -p 9000:9000 -v /Users/xuwei/Desktop/VProjects/Cocobolo/Docker:/app hello_vol tmpfs 临时数据,写入到主机内存中 [图片]

数据存储 https://docs.docker.com/engine/storage/

多容器

docker network

运行多个容器,比如前端,数据可能是独立的容器在运行,需要进行通信获取数据,使用同一个网络可以达成 创建网络: docker network create test-net docker run -p 8080:8080 --name test -v D:/test:/app --network test-net hello docker run --name js_server --network test-net server_image

docker-compose

https://docs.docker.com/compose/ (安装 docker-desktop 不需要额外安装) 如果同时运行更多的容器,都需要管理配置和指定网络,操作需要简化。 docker-compose 把项目的多个服务集合到一起,自动创建同一个网络,不需要手动指定。相当于编写脚本,将多个容器参数都写入文件中,串联一起执行 编写 docker-compose.yml: version: '3.8'

services: backend: image: node:18-alpine build: context: ./ dockerfile: Dockerfile ports: - "9000:9000" volumes: - ./backend:/app environment: NODE_ENV: production

frontend: image: nginx:alpine ports: - "80:80" volumes: - ./frontend:/usr/share/nginx/html Docker-compose 命令:

  • 运行:docker-compose up
  • 查看运行状态:docker-compose ps
  • 停止运行:docker-compose stop
  • 重启:docker-compose restart
  • 重启单个服务:docker-compose restart service-name

后续 k8s 容器编排...

https://www.bilibili.com/video/BV163411C7jE/?spm_id_from=333.337.search-card.all.click&vd_source=4b3dcc77d184ae9e210516eb13ca0b3b

学习资料: