背景
在上一篇的部署过程中,完全是把服务器当成本地开发环境来用,在服务器上拉取代码、安装依赖、运行代码,这样的部署过程过于原始了,部署步骤多,效率低;依赖直接全局安装,污染全局环境,不同项目没有做到隔离。部署流程急需升级。
使用docker简化部署
第一步的优化是上传构建产物代替上传源码,这样在服务器上就只需要运行构建产物这一个步骤了。
为什么需要docker
一个服务的运行需要通常各种各样的依赖环境,前端服务至少需要nginx和node,如果在每个服务器上都需要把这些环境都配置一遍,即使是非常熟练的工程师也不免觉得繁琐。如果存在一种技术,能生成一个完全的构建产物,这个构建产物包含了服务运行所包含的全部依赖,直接运行这个构建产物就能把服务跑起来就好了。
容器化技术就是我们所需要的解决方案。容器化技术有两个重要概念
- 镜像:镜像是一个只读的模板,包含了运行应用所需的所有代码、库、依赖和设置。它可以被看作是容器的蓝图。镜像用于创建容器。
- 容器:容器是镜像的一个运行实例,可以理解为容器就是应用+依赖+运行环境,容器具有以下特点
- 隔离性:容器提供了一个独立的运行环境,隔离了不同容器间的应用程序和进程,使它们不会相互影响。
- 可移植性:由于容器包含了应用及其所有依赖,可以在任何支持 Docker 的系统上运行,从开发环境到生产环境都能保持一致。
- 轻量级:容器不需要额外的操作系统开销,相比虚拟机更节省资源和启动更快。
容器的更多优点不再赘述,想要使用容器,就需要用到docker了,docker可以让我们方便的创建和使用容器。 下面以前端项目为例,介绍使用docker部署的流程。
docker常用命令
# 构建镜像,docker build -t 用户名/镜像名:镜像tag .
docker build -t mhhongfe/deploy-fe-demo:1.0 .
# 查看镜像
docker images
# 删除镜像
docker rmi 镜像ID
# 推送镜像到docker hub
docker push 镜像名称
# 拉取镜像
docker pull 镜像名称
# 启动容器
docker start 容器ID
# 根据镜像创建新容器,并运行容器
docker run -p 8080:80 mhhongfe/deploy-fe-demo:1.0
# 查看运行中容器
docker ps
# 查看所有容器
docker ps -a
# 停止容器运行
docker stop 容器ID
# 删除容器
docker rm 容器ID
本地构建镜像
-
准备一个前端应用 直接用vue-cli创建的项目,上传至github,前端服务
-
安装docker
- 官网下载docker客户端:docs.docker.com/desktop/ins…(这里是mac版本)
- 客户端安装后可以使用github账号登陆,登陆后命令行输入docker -v,显示docker版本信息则安装成功
-
编写dockerfile
dockerfile就是描述创建镜像流程的配置文件,详细语法可参考菜鸟教程# 使用官方 Node.js 镜像作为构建基础镜像 FROM node:18.17.1 AS builder # 安装 pnpm RUN npm install -g pnpm@8.7.0 # 设置工作目录 WORKDIR /app # 复制 package.json 和 pnpm-lock.yaml(如果有的话)到工作目录 COPY package*.json pnpm-lock.yaml* ./ # 安装应用依赖 RUN pnpm install # 复制应用源代码到工作目录 COPY . . # 构建应用 RUN pnpm run build # 使用 Nginx 镜像作为生产环境镜像 FROM nginx:alpine # 将构建产物从 /app/dist 复制到 Nginx 的默认服务目录 COPY --from=builder /app/dist /usr/share/nginx/html # 暴露端口 80 EXPOSE 80 # 启动 Nginx CMD ["nginx", "-g", "daemon off;"] -
本地构建镜像
# 构建镜像,这样命名方便后续推送到docker hub中 docker build -t 用户名/镜像名:镜像tag . # m系列芯片需要指定构建平台,不然在服务器上会出现平台不兼容的问题 # docker: image with reference dockerpull.com/mhhongfe/deploy-fe-demo:1.0 was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64. docker buildx build --platform linux/amd64 -t mhhongfe/deploy-fe-demo:2.0 .构建完之后,可以在docker客户端查看构建好的镜像
-
本地运行镜像 构建好之后在本地先运行看看效果
# 容器内是运行在80端口上,宿主机上的映射是3000端口 docker run -p 3000:80 mhhongfe/deploy-fe-demo:2.0本地访问localhost:3000,顺利看到效果
在服务器上运行容器
-
把镜像推送到docker hub
docker push mhhongfe/deploy-fe-demo:2.0 -
服务器上安装docker
在阿里云服务器上安装docker,参考安装文档 -
拉取镜像
docker pull mhhongfe/deploy-fe-demo:2.0这一步因为各种原因,可能会出现超时,错误如下:
error pulling image configuration: download failed after attempts=6: dial tcp 69.63.176.143:443: i/o timeout网上的解决方案都是配置各种国内的镜像源,但不少镜像源都不能用,最终使用dockerpull.com镜像源解决,不知道这个源能坚持多久,菜鸟学点技术真不容易。 镜像源配置参考
-
运行容器
docker run -d -p 8080:80 dockerpull.com/mhhongfe/deploy-fe-demo:2.0
使用服务器ip:8080访问服务,成功访问!
总结
第一阶段成功完成,使用docker去除了依赖安装的流程,做到了不同项目的隔离,部署流程做到了较大的简化,目前在服务器上只需要拉取镜像、运行镜像两步。
踩了两个坑
- 服务器是linux/amd64,但m系列mac上默认镜像是linux/arm64平台,不能自动兼容。解决方案是指定构建的镜像平台,通过docker buildx模拟跨平台,docker能跨操作系统提供一致的环境,但还不能跨硬件架构自动兼容。
- 从docker hub上拉取镜像,一直报超时。配置国内的镜像源可以暂时解决,但是镜像源也会被封禁,这个问题怎么解决?