提示:本系列笔记全部存在于
Github,
可以直接在
Github 查看全部笔记

这一篇主要讲述部署一个 Web 项目,项目是我曾经搞的一个 VUE 模板项目:https://github.com/orca-studio/vue-template/tree/vite-3.X

目前还没有搭建镜像私有仓库和自动化部署流程。

只能本地打包 Docker 镜像,上传 DockerHub,再服务器拉取镜像,进行启动。

本地打包 Docker 需要本地具有 Docker 环境。

Windows 或 Mac 的 Docker 环境,可以在网上查询怎么安装。

构建镜像

部署 Web 项目 的第一步是构建 镜像(Image)。

镜像(Image) 是运行时所使用的文件资源。

Docker 提供了制作 镜像(Image) 的方式:使用 build 命令执行 Dockerfile 文件。

构建 镜像(Image) 的关键 就在于 Dockerfile 文件。 Dockerfile 配置了构建镜像时所有的操作。

执行 build 时,需要提供一个 上下文目录(Context)(一般上下文目录为项目根目录)。

Docker 会将上下文目录(Context) 与子目录结构发送到 Docker 引擎 ,Docker 引擎 根据这个目录结构去构建 镜像 (Image)。

在 Dockerfile 文件中,是不允许访问 上下文目录(Context) 之外的目录。

这就是有些教程中会说不能在 Dockerfile 使用 ../ 原因。

默认情况下 Docker 会读取 上下文目录(Context) 中 Dockerfile 文件,所以一般都会将 Dockerfile 文件放在根目录。

当然也可以放在其它目录,执行 build 时使用参数指定 Dockerfile 文件

PS: 注意:在构建 镜像 时不允许访问 上下文目录(Context) 之外的目录。

Dockerfile

为了管理方便,将所有的部署相关放在 deploy 目录。

所以也将 Dockerfile 存放在 deploy 目录。

FROM nginx:latest

# 将代码copy到镜像
COPY ../dist /usr/share/nginx/html # 将 nginx 配置文件 copy 到容器内配置文件的目录下
COPY ../deploy/nginx.conf /etc/nginx # 容器应用端口
EXPOSE 80

PS:Dockerfile 支持好多指令,在此只介绍使用到的指令,其它指令有兴趣的朋友可以自行查询

  • 第一行 FROM 指令:表示使用的底层镜像,制作应用级别镜像,都需要依赖运行环境。web 项目的运行环境为 Nginx 服务器。

    PS: 之前说过, 镜像是分层存储的,构建镜像可以简单的理解为在现有镜像上添加一层。

  • 第二行 COPY 指令:表示 复制文件,将本地的目录或者文件 复制到镜像指定目录下。

    将 ./dist 目录,也就是项目编译生成的代码目录复制到 镜像中 /usr/share/nginx/html 目录

    PS:所有相对目录都是以 上下文目录(Context) 为基准,所以 dist 目录访问是 ./dist,而非 ../dist。

  • 第三行 COPY 指令:表示将 nginx.conf 配置文件 复制到 /etc/nginx。

    PS:所有相对目录都是以 上下文目录(Context) 为基准,所以 nginx.conf 目录访问是 ./deploy/nginx.conf,而非 ./nginx.conf。

    web 项目 容器 运行的是 Nginx 服务器, 自己制作的 web 镜像 镜像(Image) 只是将生成的静态文件挂载到 Nginx 服务器上。

    nginx.conf 文件是用来配置 Nginx 挂载路由等信息。

  • 第四行 EXPOSE 指令:暴露端口号,启动容器时使用 ports 映射容器内部的端口号就是此命令暴露的。

Nginx 镜像中,暴露了 80 端口运行 Nginx 服务器,Dockerfile 中只暴露 80 端口,在启动时 80 端口直接启动的是 Nginx 服务器。

注意:不允许直接使用 ./nginx.conf 访问,会被识别成以 上下文目录(Context) 下的 nginx.conf

但是允许以 上下文(目录)为相对目录的基准目录。

nginx.conf

在 deploy/nginx.conf 文件中编写 Nginx 配置。 构建镜像(Image)时会将此文件复制到镜像

PS: 也可以使用类似上一篇中的将 nginx.conf 挂载到宿主环境中。

events {
worker_connections 1024;
} http {
include mime.types;
default_type text/html;
sendfile on;
keepalive_timeout 65;
charset utf-8;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
server {
listen 80; location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
}
  • root: 此属性设置根目录,当前根目录设置为 /usr/share/nginx/html,静态文件都存储在此目录。
  • index: 此属性指定网站初始页面。 也就是 /usr/share/nginx/html/index.html
  • try_files: 此属性将所有的访问都转为 index.html 。单页面程序的路由都是请求同一个 HTML,由 JS 内部判断的路由页面,

    类似 webpack-dev-server 中 historyApiFallback 属性

执行构建

执行构建 镜像(Image) 使用的命令是 docker build。

为了执行方便,在 package.json 中添加 deploy 命令执行构建

每次构建 镜像(Image) 前,先进行项目编译。也就是执行 npm run build 命令。当编译成功后才执行 docker build 。

PS: npm-run-all 是一个 NPM 包,用于执行多个脚本

PS: Docker Hub 没有账号的需要先进行注册:https://hub.docker.com/

docker build 命令中使用了几个参数

  • -t 构建的镜像名称。 其中 yxs970707 是 Docker Hub 中的用户名称。

    当前没有构建私库,先推送到 Docker Hub。将 yxs970707 改为自己用户名称或组织。

    : 后的为当前镜像的 标签(tag),一般情况下会设置版本号。

    也可以使用多个 -t 设置多个版本号
  • -f Dockerfile 文件地址,Dockerfile 文件存在了 deploy 目录,所以需要指定文件地址。
  • 最后一个点 . 表示设置当前目录为 上下文目录(Context)。

PS:标签(tag) 可以随意设置,标签(tag) 可以根据实际情况使用版本号

PS: 构建镜像时可以设置多 标签(tag),添加多个 -t

此时,执行 npm run deploy 便可以构建镜像(Image)。构建镜像(Image)时,每一句命令都具有清晰的信息。构建成功后就可以在本地 Docker 中看到此镜像

PS:第一次构建可能会慢一些,因为本地没有 Nginx 镜像,需要 pull。

PS:镜像(Image) 的分层其实每一句命令都是一层。


测试镜像

成功构建镜像后可以先在本地测试

在此将本地 3333 端口号映射到了容器。可以根据情况随意设置未被使用的端口号,

如果未出意外的话将会启动一个 容器,容器状态为 RUNNING。


如果启动时出错的话,可以点击容器查看错误日志进行分析

按照步骤理论上不会有什么问题,如有未成功的可以查询日志尝试解决,实在解决不了可以留言。

推送 Docker Hub

镜像推送 Docker Hub 很简单,只需要在 Docker Desktop 中登录账号点击 push 即可

PS:之后部署私有仓库之后可以推送到私有仓库

push 成功后就可以在 Docker Hub 中搜到此镜像



部署容器

最简部署

容器的最简部署方案是只设置端口号

拉取镜像可能有些延迟,因为 Docker 配置了国内源,需要时间来同步

version: '3.9'
services:
nginx:
image: yxs970707/deploy-web-demo:1.0.0
container_name: web
restart: always
ports:
- 7777:80

PS:镜像(Image)的 标签(tag) 设置的为 1.0.0,拉取镜像时需要指定

使用 Portainer 部署完毕后就可以访问服务器进行访问。


volumes 挂载

在上面将所有文件都存放镜像中,并没有使用 volumes 将 /usr/share/nginx/html 目录挂载到宿主机中。

接下来就实现这一操作,将数据挂载到宿主机中。

将数据挂载到宿主机中可以实现不更新镜像和容器直接更新前端项目。

但是真实情况下并不推荐这样做。这里只是介绍下可以这样做,在后续自动化部署时还是根据镜像版本更新。

非具名 volumes 覆盖问题

之前都是使用宿主目录直接挂载容器内目录。

直接使用宿主目录挂载,在容器启动时会使用宿主目录覆盖容器目录。

version: '3.9'

services:
nginx:
image: yxs970707/deploy-web-demo:1.0.0
container_name: web
restart: always
ports:
- 7777:80
volumes:
- /volumes/web/html:/usr/share/nginx/html

更新 YMAL 文件,添加挂载 /usr/share/nginx/html 目录。

使用此文件重新部署,访问时 Nginx 会提示 403,也就是根本没有找到该地址

/usr/share/nginx/html 目录是存储前端文件的目录。

在服务器查看会发现挂载目录并没有任何文件,进入容器内部查询 /usr/share/nginx/html 也没有任何文件

也就是说 Docker 在启动容器时,使用宿主目录(空目录)覆盖了容器内目录。


docker exec -it web /bin/sh 进入容器

可以在宿主目录创建一个文件测试,在此只贴出测试结果。有兴趣的可以自行测试。

具名 Volumes

解决数据挂载问题,需要创建具名的 Volumes。

Docker 中 Volume 是一个完整的模块。具有很强大的功能。

甚至可以将数据挂载到其它机器上,在此只使用 Volume 完成目前的需求。

其它功能,有兴趣的朋友可以自行查询稳定。

Volume 可以使用命令先进行创建,然后在挂载时使用。当然可以在 Docker Compose 创建。

version: '3.9'

volumes:
web-html:
name: web-html
driver: local
driver_opts:
o: bind
type: none
device: /volumes/web/html services:
nginx:
image: yxs970707/deploy-web-demo:1.0.0
container_name: web
restart: always
ports:
- 7777:80
volumes:
- web-html:/usr/share/nginx/html

YAML 文件中 volumes 就是创建具名的数据卷。

这个数据卷使用了本地数据卷,将数据卷绑定本地 /volumes/web/html 目录

PS: 数据卷还具有其它绑定方式,比如使用 IP 绑定其它机器。

然后使用 数据卷名称(web-html) 挂载容器 /usr/share/nginx/html

注意,使用数据卷名称挂载时, /volumes/web/html 目录必须存在,目录下不允许有文件。

使用此 yml 部署便可以将数据挂载到 /volumes/web/html。


仔细观察的情况下, Portainer 可视化工具中在 Volume 项此时具有一个 web-html 的数据卷

在其详细信息中可以看到具体详情。

其中具有一个 Mount path 属性,这个属性值是此数据卷的目录。

其实在 Docker 挂载数据卷时,会将此目录与容器内进行挂载。

另外还有一个 device 属性,这个数据是与数据卷绑定的目录。Linux 具有一种可以将 Mount path 和 device 绑定为一个目录方案

当然还可以使用其它绑定方案,将数据卷绑定到其它目录。甚至可以绑定到其它机器

私有化轻量级持续集成部署方案--03-部署web服务(上)的更多相关文章

  1. 私有化轻量级持续集成部署方案--04-私有代码仓库服务-Gitea

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 企业级最流行的私有代码仓库是 Gitlab, 一开始我也打算部署 Gitlab作为私有代码仓库. 但部署完 d 成后 ...

  2. 私有化轻量级持续集成部署方案--06-私有镜像仓库-Harbor

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 针对私有镜像仓库的问题,Docker 官方提供了搭建仓库服务的镜像服务:registry,使用此镜像就可以部署私有仓 ...

  3. 私有化轻量级持续集成部署方案--05-持续部署服务-Drone(上)

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 持续部署概述 持续部署是能以自动化方式,频繁而且持续性的,将软件部署到生产环境.使软件产品能够快速迭代. 在之前部署 ...

  4. 私有化轻量级持续集成部署方案--07-私有NPM仓库-Verdaccio

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 对于个人来说,私有NPM仓库 作用性基本很小,但是对于企业,私有NPM仓库 可以保护代码暴露,具有很大的意义. 也是 ...

  5. 私有化轻量级持续集成部署方案--02-Nginx网关服务

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 这一篇中使用 Nginx 部署网关中心,用来代理服务器中服务.网关中心有优点也有缺点,也可以不采用网关系统. 部署 ...

  6. 私有化轻量级持续集成部署方案--03-部署web服务(下)

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 配置接口代理 前后端分离情况下,前端请求后端接口最常用的一种方式就是使用反向代理,反向代理会让浏览器认为是同源路径, ...

  7. 持续集成环境--Tomcat热部署导致线程泄漏

    一.问题由来 我们组用jenkins部署了持续集成环境,(jenkins部署war包到远程服务器的tomcat). 每次提交了代码,jenkins上一键构建,就可以自动拉取最新代码,打war包,热部署 ...

  8. 用Jenkins+Gradle+Jetty实现持续集成、测试、部署

    自动集成有很多种方案,本例用到的工具是Jenkins(前身Hudson)+Gradle+Jetty,关于Gradle可参考上一篇,Gradle常见问题. 本例项目名称: WAP Jetty 安装Jen ...

  9. 持续集成之Jenkins自动部署war包到远程服务器

    一.无war包链接的情况 无war包链接时,需先下载war包到本地,然后执行: ---------------------------------------------以下部分为转载-------- ...

随机推荐

  1. 使用 Docker 部署 Seata Server(分布式事务解决方式)

    1.获取镜像 ## 使用下面命令获取最新版本的镜像,此时我的版本是1.3.0 ## 或者可以使用docker pull seataio/seata-server:latest获取最新的镜像 docke ...

  2. js 模块化 -- export 时 一个默认和多个默认的写法

    js文件 只有一个  food 类,一般写 export {food} 或者 export {food as default} 那么如果有多个呢? 这样 export {food, food2} 或者 ...

  3. [转]Vue之引用第三方JS插件

    1.绝对路径引入,全局使用. 在index.html文件中使用script标签引入插件. 该种方式就是上面演示ckplayer插件使用的方式. 备注: 这种方式的引用,会在开启ESLint时,报错,可 ...

  4. Sentry 开发者贡献指南 - Feature Flag

    功能 flag 在 Sentry 的代码库中声明. 对于自托管用户,这些标志然后通过 sentry.conf.py 进行配置. 对于 Sentry 的 SaaS 部署,Flagr 用于在生产中配置标志 ...

  5. 通过HTML+CSS+Javascript实现向下滚动滚动条出现导航栏并出现回到顶部按钮点击按钮回到顶部(一)

    回到顶部实例一 效果:默认隐藏导航栏,当滚动条滚到超过300px后导航栏和按钮出现,点击回到顶部按钮回到顶部,并隐藏导航栏和按钮(导航栏和按钮都是固定定位) <!doctype html> ...

  6. Collection的使用

    常用方法 Modifier and Type Method and Description boolean add(E e) 确保此集合包含指定的元素(可选操作). boolean addAll(Co ...

  7. Python 安装MySQL 错误处理

    正常情况下如果使用python 连接数据库需要安装 python-MySQL 类库 #pip install python-MySQL 等待安装完成即可 使用时 import MySQLdb ==== ...

  8. jsp加载css失效的解决方法

    问题: 有时候大家修改了css文件里的样式,但是刷新浏览器,利用工具看样式的时候,发现样式根本没加载或者说没更新, 其实这出现的问题就是缓存的问题 解决: 如何避免发生这种事,其实很简单,只需要每次请 ...

  9. 使用Hot Chocolate和.NET 6构建GraphQL应用(3) —— 实现Query基础功能

    系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 需求 在本文中,我们通过一个简单的例子来看一下如何实现一个最简单的GraphQL的接口. 实现 引入Hot Cho ...

  10. How to find out which process is listening upon a port

    When we covered port scanning a short while ago we discovered how to tell which ports had processes ...