docker 镜像部署

2024/03/04 工作记录 共 4216 字,约 13 分钟

简介

我们经常听到这样的话:这个程序在我环境里明明是好的啊,怎么到你这就不行了呢??原因:安装包的问题,大概率是环境的问题

安装软件的时候在不同的环境需要执行不同的命令,当我们把代码部署到不同的操作系统的服务器上,要将其运行起来,那就需要针对每个环境单独写一套部署脚本,这样就会增加维护成本,而且还会出现一些问题。

没有什么是加一层中间层不能解决的,如果有,那就再加一层,这次我们要加的中间层是 Docker。

程序是跑在操作系统上的,而操作系统上又装了各种不同版本的依赖库和配置,这些被程序所依赖的信息,我们统称为”环境”

环境:依赖库+配置+操作系统

什么是docker?

Docker 就是这样一款可以将程序和环境打包并运行的工具软件。它通过 Dockerfile 描述环境和应用程序的依赖关系, docker build 构建镜像, docker pull/push 跟 Docker Registry 交互实现存储和分发镜像,docker run 命令基于镜像启动容器,基于容器技术运行程序和它对应的环境,从而解决环境依赖导致的各种问题

基础镜像:最底层的镜像,通常包含一个最小化的操作系统环境(依赖库+文件系统+用户空间)比如:FROM python:3.9

dockerfile文件:就像一份 todo list,要求在基础镜像的基础上按着 todo list 挨个执行命令

容器镜像:我们用命令行执行 docker build 的时候,Docker 软件就会按着 Dockerfile 的说明,一行行构建环境+应用程序。最终将这个环境+程序,打包成一个类似”压缩包”的东西,我们叫它容器镜像(container image)。

Registry :镜像仓库,存放镜像的地方,可以理解为 github,可以存放代码,可以存放镜像

容器:我们可以跑到目的服务器上,执行 docker pull 拿到容器镜像。然后执行 docker run 命令,将这个类似”压缩包”的容器镜像给”解压缩”,获得一个独立的环境和应用程序并运行起来。这样一个独立的环境和应用程序,就是所谓的容器(container),我们可以在一个操作系统上同时跑多个容器。且这些容器之间都是互相独立,互相隔离的。容器本质上只是个自带独立运行环境的特殊进程,底层用的其实是宿主机的操作系统内核。

docker 可视化工具页面

Docker 和虚拟机的关系:这个容器是不是很像我们用 vmware 或 kvm 整出来的传统虚拟机?但不同的是,传统虚拟机自带一个完整操作系统,而容器本身不带完整操作系统,容器的基础镜像实际上只包含了操作系统的核心依赖库和配置文件等必要组件。它利用一个叫 Namespace 的能力让它看起来就像是一个独立操作系统一样。再利用一个叫 Cgroup 的能力限制它能使用的计算资源

Docker 的架构原理

它是经典的 Client/Server 架构,。Client 对应 Docker-cli, Server 对应 Docker daemon。我们在命令行里敲 Docker 命令,使用的就是 Docker-cli.

Docker-cli 会解析我们输入的 cmd 命令,然后调用 Docker daemon 守护进程提供的 RESTful API,守护进程收到命令后,会根据指令创建和管理各个容器。再具体点,Docker Daemon 内部分为 Docker Server、Engine 两层。Docker Server 本质上就是个 HTTP 服务,负责对外提供操作容器和镜像的 api 接口,接收到 API 请求后,会分发任务给 Engine 层,Engine 层负责创建 Job,由 Job 实际执行各种工作。

docker build:如果你执行的是 docker build 命令,Job 则会根据 Dockerfile 指令,像包洋葱皮似的一层层构建容器镜像文件。

docker pull/push:如果你执行的是 docker pull 或 push 之类的镜像推拉操作,Job 则会跟外部的 Docker Registry 交互,将镜像上传或下载

docker run:如果你执行的是 docker run 命令,Job 就会基于镜像文件调用 containerd 组件,驱使 runC 组件创建和运行容器。

Docker Compose 是什么?

我们现在知道了 Docker 容器 本身只是一个特殊进程,但如果我想要部署多个容器,且对这些容器的顺序有一定要求呢?比如一个博客系统,当然是先启动数据库,再启动身份验证服务,最后才能启动博客 web 服务。按理说挨个执行 docker run 命令当然是没问题的,但有没有更优雅的解决方案?有。我们可以通过一个 YAML 文件写清楚要部署的容器有哪些,部署顺序是怎么样的,以及这些容器占用的 cpu 和内存等信息。

通过一行Docker-compose up命令,开始解析 YAML 文件,将容器们一键按顺序部署,就完成一整套服务的部署。这其实就是 Docker Compose 干的事情。

docker 构建的镜像产物

Docker Swarm 是什么?

Docker 解决的是一个容器的部署。Docker Compose 解决的是多个容器组成的一整套服务的部署。那 Docker Swarm 就更高维度了,它解决的其实是这一整套服务在多台服务器上的集群部署问题。比如在 A 服务器坏了,就将服务在 B 服务器上重新部署一套,实现迁移,还能根据需要对服务做扩缩容。

k8s 跟 Docker Swarm 做的事情很像?没错,其实 Docker Swarm 是 k8s 的竞品,既然是竞品,那它们做的事情其实区别就不大了。现在回过头来看 Docker 容器和 k8s 之间的关系,思路就清晰了。Docker 部署的容器,其实就是 k8s 调度的 Pod 里的 container,它们都叫容器,其实是一回事。只不过 k8s 除了支持 Docker 的容器外,还支持别人家的容器。Docker Compose 基于多个 container 创建的一整套服务,其实就是 k8s 里的 pod。而 Docker Swarm 做的事情和 k8s 一样,本质上就是在调度 pod。回过头来看下 k8s 的官方定义,叫容器编排引擎,将它理解为,以 API 编程的方式管理安排各个容器的引擎,是不是就特别精辟。

我们再回过头来看下 Docker 的图标,是一个个集装箱,放在一艘船上,这一个个集装箱指的就是互相隔离的容器,而 k8s 的图标,则是一个轮船上的方向盘,意思是 k8s 控制着轮船的航向,其实指的就是调度容器。这波联想就非常形象了

构建镜像

docker build -t node-docker .

docker build:这是告诉Docker你想要构建一个新的镜像的命令。

-t node-docker:-t指定一个标签(tag),通常用于镜像的版本控制和识别,默认使用latest。

.:这指定了Dockerfile的位置。.表示当前目录,意味着Docker会在当前工作目录查找名为Dockerfile的文件,并使用它来构建镜像。

执行docker run 命令运行镜像

每条指令都会创建一个新的层,Docker 使用写时复制(Copy-on-write)机制,重用已有层以减少存储需求。

命令运行镜像

docker run node-docker

运行的时候,还可以再带一些别的参数,这个就具体情况具体分析了

DockerFile 常见的指令

FROM:指定基础镜像。 Dockerfile 都必须以一个 FROM 指令开始,用来指定一个已存在的镜像。

ENV:设置环境变量。

RUN:在镜像中执行命令。常用于安装软件包。

COPY:将文件或目录复制到镜像中。

WORKDIR:设置工作目录,即容器内部的当前目录。

EXPOSE:声明容器运行时监听的端口。

CMD:提供容器默认执行的命令。Dockerfile 中可以有多个 CMD 指令,但只有最后一个会生效。

FROM ghcr.io/puppeteer/puppeteer:latest

USER root

WORKDIR /app

COPY package.json yarn.lock ./

RUN yarn install

COPY . .

RUN yarn build

# 暴露应用程序端口(如果应用程序需要监听端口)
EXPOSE 3000

# 定义启动命令
CMD ["node", "app.js"]

什么是镜像部署

将容器镜像上传到镜像仓库。镜像部署服务从镜像仓库中拉取每个镜像,并自动将其部署。

部署完成后,服务会提供负载均衡和自动扩展,以确保应用程序的高可用性和可伸缩性。如果发现容器不再需要或不再需要自动扩展,镜像部署服务将自动停止或缩小容器。

在实际开发中都是自动化脚本实现的,我们只需要写好dockerfile文件就好了

安装docker

docker version: 查看是否安装了docker

docker info: 查看更加详细的docker信息

docker run: 创建和启动docker

docker ps: 列出正在运行的docker

docker images: 列出本地docker映像

我遇到的问题

使用官方提供的镜像,若官方镜像运行有问题

我就去网上寻找别的镜像,结果一堆错误,我用了FROM alpine:3.19

结果各种错误,原因是alpine 只提供了最基础的功能,简单理解就是阉割版

错误1: audioBuffer Failed to execute ‘decodeAudioData’ on ‘BaseAudioContext’: Unable to decode audio data

错误2: PIXI error Unable to auto-detect a suitable renderer.

错误3: The requested image’s platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

建议:一定要使用官方提供的镜像,若官方镜像运行有问题;

那就一步一步进行排查问题。检查docker 版本,看一下系统架构,命令行添加参数,等等,具体问题具体分析,不建议自己网上查找或者使用第三方,容易残缺不全

走了不少弯路,浪费了一些时间,最后还是使用官方的镜像

总结

碰到自己知识盲区的时候,先看多看几遍官方文档。碰到问题解决不了了,弄一个不含任何业务代码的最小demo,多尝试。有时候会陷入自己思维怪圈,所以我们需要请教身边人。

做好问题记录,碰到什么问题,尝试过哪些解决方案。问题解决之后进行复盘


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents