写给前端仔仔的docker实战

那是19年,正在上大三的柏成用一堆屎山代码从零搭建了一款个人博客,对于一个刚刚入门的前端崽来说,想要部署在云服务器上,需要安装mysql,redis,配置环境变量 ....... 过五关斩六将,每一步都踩了好多好多坑

服务器到期后,柏成也没再续费.......

21年,柏成又想重启个人博客,哐哐哐一顿操作,顺利上线,还精挑细选了域名 burc.com.cn

服务器到期后,柏成也没再续费.......

25年初,柏成又想重启个人博客,问题来了,那么能不能一行命令,自动安装所有依赖,完成部署操作呢?

答案是:可以!docker 闪亮登场

docker 核心概念

我们先了解下 docker的几个核心概念:镜像、容器、仓库、Dockerfile

  • 镜像(Image): 镜像是容器的"模板",是将软件环境打包好的模板,用来创建容器的,一个镜像可以创建多个容器
  • 容器(Container): 应用程序及其依赖环境的运行实例,启动一个镜像就是一个容器,容器与容器之间相互隔离,并且互不影响, 可以简单理解为一个"轻量级、可移植的微型操作系统"
  • 仓库(Registry) : 类似于代码托管平台(如 GitHub),我们可以制作镜像然后 push 推送到云端的仓库,也可以从仓库 pull 拉取镜像
  • Dockerfile: 包含了一系列指令和配置,用于描述如何组装一个 docker镜像,相当于列出了镜像所需的原材料。通过 Dockerfile,你可以自动化地构建镜像,确保在不同的环境中都可以复现相同的容器

下面这张图展示了他们之间的关系

docker 基础操作

这里就不做过多介绍

docker-compose

通过一个单独的 YAML 文件定义和管理多个 Docker 容器的配置

统一配置 :通过一个 docker-compose.yml 文件,可以同时定义多个服务及其依赖关系(例如数据库、缓存、反向代理等)

一键管理:只需一条命令即可启动、停止所有服务

  • 启动:docker-compose up -d
  • 停止:docker-compose down

我们先对docker-compose.yml 有个大体认知,至于YAML文件里的内容是什么,最后附上源码

容器化部署实战

柏成通过 Docker 和 Docker Compose 实现了多容器化部署,包含后端服务、前端服务、数据库服务、redis服务以及 Nginx 服务,目录结构如下

前端服务(frontend)

react 文件夹下是前端 build打包的产物

Dockerfile 定义了如何构建前端镜像

powershell 复制代码
# 使用官方 Nginx 镜像作为基础镜像
FROM nginx:latest

# 将当前目录的内容拷贝到 Nginx 默认的静态文件目录
COPY ./react/ /usr/share/nginx/html/

# 暴露 Nginx 默认端口
EXPOSE 80

后端服务(backend)

node 文件夹下是整个后端项目

Dockerfile 定义了如何构建后端镜像

powershell 复制代码
# 使用 Node.js 构建阶段
FROM node:18

# 设置工作目录
WORKDIR /app

# 复制宿主机 ./node/目录中的文件 到容器的 /app/node/
COPY ./node/ ./

# 更换 npm 镜像源为淘宝镜像
RUN npm config set registry https://registry.npm.taobao.org/

# 禁用 SSL 证书验证(可选,只有在其他解决方法无效时使用)
RUN npm config set strict-ssl false

# 安装依赖
RUN npm install

# 暴露后端端口,这里其实没用。我们在node后端服务中暴露了5000端口,以node进程暴露的为准
# EXPOSE 5000

# 启动后端服务
CMD ["npm", "run", "prd"]

数据库服务

初始化脚本

blog.sql 是数据库初始化脚本,用于创建表和初始数据

我们在docker-compose.yml中通过 volumes 将其映射到了 mysql容器内部 /docker-entrypoint-initdb.d/blog.sql

/docker-entrypoint-initdb.d/是一个特殊目录,在 mysql容器初始化时,会自动执行放置在该目录下的 .sql 文件

powershell 复制代码
volumes:
   - ./mysql/blog.sql:/docker-entrypoint-initdb.d/blog.sql 

数据持久化

mysql_data 是用于 MySQL 数据库的持久化存储挂载点

默认情况下,所有数据存储在容器的文件系统中。如果容器被删除或重新创建,数据会丢失

我们将主机上的mysql_data目录挂载到容器内,用来持久化存储数据

当我们新增、更新 mysql数据时,mysql数据会映射到本地目录;反之当容器重启后,也会自动加载 ./mysql/mysql_data中的文件,自动恢复数据

powershell 复制代码
volumes:
   - ./mysql/mysql_data:/var/lib/mysql

Nginx服务

nginx.conf文件是 Nginx 的配置文件,用于反向代理前端和后端服务,以及提供静态资源服务

powershell 复制代码
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    client_max_body_size 8M; # (设置客户端请求体最大值) 
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            proxy_pass http://frontend:80;  # 800 是 frontend 容器内部端口
            index  index.html index.htm;
        }

        # 配置后端 API 代理
        location /api/ {
            proxy_pass http://backend:5000;  # 替换为你的后端服务地址,5000 是 backend 容器内部端口
            
           # 超时设置
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;

            # 禁用缓存
            proxy_buffering off;

            # 保持连接
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

docker-compose.yml

docker-compose.yml全部源码如下

powershell 复制代码
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80" # 将主机的 80 端口映射到容器的 80 端口
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载自定义的 Nginx 配置文件
    depends_on:
      - frontend
      - backend
    networks:
      - app_network
      
  frontend:
    build:
      context: ./frontend # 指定前端项目 ./fronten文件夹作为构建上下文
      dockerfile: Dockerfile # 指定构建镜像时使用的 Dockerfile
    ports:
      - "3001:80" # 将容器内的 80 端口映射到主机的 3001 端口,3001端口供外部访问
    depends_on:
      - backend # 指定该服务依赖 backend,确保 backend 服务先启动
    networks:
      - app_network

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "8001:5000" # 将容器内的 5000 端口映射到主机的 8001 端口,8001端口供外部访问
    depends_on: 
      # 后端服务依赖 mysql 和 redis 服务,确保它们先启动
      mysql: # backend 服务会等待 mysql 服务的健康检查(healthcheck)通过后再启动
        condition: service_healthy
      redis: # backend 服务会等待 redis 服务容器启动
        condition: service_started
    networks:
      - app_network

  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: always
    command: --default-authentication-plugin=mysql_native_password # 身份验证协议兼容
    ports:
      - "3307:3306" # 将容器内的 3306 端口(MySQL 默认端口)映射到主机的 3307 端口
    environment:
      MYSQL_ROOT_PASSWORD: 123456 # 设置 root用户密码
      MYSQL_DATABASE: blog # 初始化时会自动创建一个名为 blog 的数据库
    volumes:
      # 将主机上的 ./mysql/blog.sql 文件(一个 SQL 脚本文件)挂载到容器内的 /docker-entrypoint-initdb.d/blog.sql 目录
      # 特殊目录 /docker-entrypoint-initdb.d/ : 在容器初始化时,会自动执行放置在 /docker-entrypoint-initdb.d/ 目录中的 .sql 文件
      # 因此,当容器第一次启动时, 执行 blog.sql 来初始化数据库表结构
      - ./mysql/blog.sql:/docker-entrypoint-initdb.d/blog.sql 
      # 默认情况下,所有数据存储在容器的文件系统中。如果容器被删除或重新创建,数据会丢失
      # 我们将主机上的./mysql/mysql_data目录 挂载到容器内,用来持久化存储数据
      # 当我们通过项目向 MySQL新增、更新数据时,MySQL 数据目录会地映射到本地目录;反之当容器重启后,会自动加载 ./mysql/mysql_data中的文件,自动恢复数据
      - ./mysql/mysql_data:/var/lib/mysql
    healthcheck: # 定义健康检查,确保 mysql 服务在正常运行后标记为健康
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p666666"]
      interval: 10s
      timeout: 5s
      retries: 3
    networks:
      - app_network

  redis:
    image: redis:alpine
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - app_network

# 显式声明一个网络,并将服务连接到该网络(默认创建的网络好像不太行。。。)
networks:
  app_network:
    driver: bridge

结语

这样我们就实现了 docker容器化部署,通过一行命令即可启动所有服务并将其运行在后台,以后,柏成个人博客再次迁移服务器时,就不用一个一个安装服务了,爽歪歪啊!

powershell 复制代码
docker-compose up -d
相关推荐
Double__King2 分钟前
巧用 CSS 伪元素,让背景图自适应保持比例
前端
Mapmost3 分钟前
【BIM+GIS】BIM数据格式解析&与数字孪生适配的关键挑战
前端·vue.js·three.js
一涯4 分钟前
写一个Chrome插件
前端·chrome
鹧鸪yy11 分钟前
认识Node.js及其与 Nginx 前端项目区别
前端·nginx·node.js
跟橙姐学代码12 分钟前
学Python必须迈过的一道坎:类和对象到底是什么鬼?
前端·python
汪子熙14 分钟前
浏览器里出现 .angular/cache/19.2.6/abap_test/vite/deps 路径究竟说明了什么
前端·javascript·面试
Benzenene!15 分钟前
让Chrome信任自签名证书
前端·chrome
yangholmes888815 分钟前
如何在 web 应用中使用 GDAL (二)
前端·webassembly
jacy17 分钟前
图片大图预览就该这样做
前端