Skip to content

docker 命令了解

sh
# 0.查看 images
docker images

# 1.根据当前目录下的 Dockerfile 打包
docker build -t my-vuejs-app .

# 2.再次查看 images
docker images

# 3.查看运行所有的容器
docker ps

# 4.运行
docker run --name my-vuejs-app -p 80:80 443:443 -d my-vuejs-app

# 5.再次查看运行所有的容器
docker ps

# 6.停止容器
docker container stop my-vuejs-app

# 7.查看所有容器(包括已停止的)
docker ps -a

# 8.删除容器
docker constainer rm  my-vuejs-app

# 9.再次查看所有容器(包括已停止的)
docker ps -a

# 10.删除镜像
docker container rmi my-vuejs-app:latest

# 11.再次查看所有镜像
docker images

部署打包好的静态文件

如果是手动部署, 推荐这种方式

这里以 vite 构建工具创建的项目为例, 包括但不限于 vue.js/react.js 项目

  • 使用默认的 nginx 配置文件
txt
.
├── Dockerfile    # Dockerfile
├── README.md     # 项目说明文件
├── dist          # 项目打包后的静态文件
│   ├── assets
│   │   ├── index-653XRtVo.css
│   │   └── index-C0gxKVtj.js
│   ├── index.html
│   └── vite.svg
└── docker-compose.yaml
sh
#!/bin/bash
if [[ -d "./build" ]]; then
  rm -rf "./build"
fi

if [[ -f "./build.zip" ]]; then
  rm -rf "./build.zip"
fi

mkdir "./build"

npm run build

mv dist ./build/

cp Dockerfile docker-compose.yaml README.md ./build

zip ./build.zip -r ./build
Dockerfile
FROM nginx:stable

WORKDIR /app
COPY . /app

RUN rm -rf /usr/share/nginx/html/index.html
RUN mv /app/dist/* /usr/share/nginx/html/

# nginx will use default config file: /etc/nginx/conf.d/default.conf

RUN echo "deploy completed"
yaml
services:
  app:
    build:
      context: "."
    container_name: app
    ports:
      - 8080:80
    restart: always
sh
# 1. 进入项目目录, 授予 build.sh 执行权限
chmod +x ./build.sh

# 2. 执行打包脚本
./build.sh

# 3. 将文件上传到服务器并解压,并进入 build 目录

# 4. 用docker部署
docker compose up -d

使用容器打包并部署 VueJS 项目

这种方式一般用于 CI/CD(如 Github Action)

  • 打包部署并且使用自定义的nginx配置
Dockerfile
### 1. 用 node:lts-alpine 镜像来打包项目文件
FROM node:lts-alpine AS build-app

# 设置工作目录 & 将项目文件复制到容器中
WORKDIR /app
COPY . /app

# 设置 npm 源(加速)
RUN npm config set registry https://registry.npmmirror.com/

# 安装pnpm 安装项目依赖 打包(怕出现幻影依赖的bug,所以用pnpm)
RUN npm install pnpm -g && \
  pnpm install --frozen-lockfile && \
  pnpm run build

# 可以在这里执行测试基本,检查代码的基本错误
# RUN pnpm test

RUN echo "🎉 build completed"

### 2. 用 nginx 部署打包好的文件
FROM nginx:stable AS deploy-app

# 将需要文件从上一个打包步骤的容器中复制到本容器
# dist       : 项目打包后的文件
# nginx.conf : nginx 配置文件(放在项目根目录下)
# ssl_keys   : 配置 https 需要的证书文件
COPY --from=build-app /app/dist       /usr/share/nginx/html/dist
COPY --from=build-app /app/nginx.conf /etc/nginx/nginx.conf

RUN echo "🎉 deploy completed"
nginx
user  nginx;
worker_processes auto;

#error_log  /var/log/nginx/error.log;
#pid        /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log off;

    server {
        # set server name and listen port
        listen 80 default_server;
        server_name www.example.cn;

        # web root directory
        root /usr/share/nginx/html/dist;
        index index.html;

        # for vue-router history mode
        location / {
          try_files $uri $uri/ /index.html;
        }
    }
}

打包 express 项目

Github 在线代码

txt
.
├── Dockerfile          # docker 构建镜像的配置文件
├── docker-compose.yaml # docker-compose 配置文件
├── .dockeringore       # docker 构建镜像时需要忽略的文件
├── README.md           # 项目说明文件
├── biome.json          # biome 配置文件
├── package.json        # package.json
├── pm2.config.cjs      # pm2 配置文件
├── pnpm-lock.yaml      # pnpm 锁定依赖文件
└── server.js           # 项目入口

1 directory, 8 files
Dockerfile
# 镜像: https://hub.docker.com/_/node
FROM node:lts-alpine

# 设置环境变量, 可以用 docker-compose 配置文件的 environment 覆盖
# ARG: 构建镜像时传递的参数,不会保存到镜像中(默认参数)
# ENV: 启动容器时传递的参数,会保存到镜像中
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

# 构建镜像的工作目录(/app 是容器中的路径)
# 在 docker-compose 中映射 public 目录会用到
WORKDIR /usr/local/app

# 将当前宿主机目录复制到容器中的工作目录
COPY . .

# 使用淘宝镜像源 & 安装依赖
RUN npm config set registry https://registry.npmmirror.com/ && \
    npm install -g pnpm && \
    pnpm install

# 暴露端口(注意要和代码中的端口一致)
EXPOSE 3000

# 执行启动命令, 需要在 package.json 中配置
CMD ["npm", "run", "start"]
yaml
---
services:
  express-mock-server:
    build:
      context: .
      tags:
        - express-mock-server
    ports:
      - 8000:8000
    environment:
      # 环境变量控制
      - NODE_ENV=production
      - APP_HOST=http://localhost:8000
txt
node_modules
npm-debug.log
pnpm-debug.log
.git
.gitignore
.env
json
{
  "name": "express-mock-server",
  "version": "0.0.1",
  "main": "./server.js",
  "type": "module",
  "scripts": {
    "dev": "pm2 start ./server.js --watch --name mock-server",
    "start": "pm2-runtime start ./pm2.config.cjs --env production",
    "stop": "pm2 stop ./pm2.config.cjs"
  },
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^5.1.0",
    "mockjs": "^1.1.0",
    "pm2": "^6.0.8"
  }
}
js
// prettier-ignore
module.exports = {
  apps: [
    {
      name: "express-mock-server", // 启动时的名称
      script: "./server.js",       // 执行的脚本
      cwd: ".",                    // 执行的工作目录
      watch: false,                // 是否监听文件变化并重启
      instances: 1,                // 需要启动多少个实例(多进程负载均衡)
      autorestart: true,           // 自动重启(如果意外退出)
      max_memory_restart: "500M",  // 如果内存占用超过 500M 则重启
      env: {                       // 自动设置环境变量, 不再需要 cross-env 手动设置
        NODE_ENV: "production",
        TZ: "Asia/Shanghai",       // 设置时区为上海, 否则默认是美国时间, 会影响 Date API
        APP_PORT: 8000,
      },
    },
  ],
};
js
import cors from "cors";
import express from "express";
import Mock from "mockjs";

const { mock } = Mock;

/////////////////////////////////////////////////
//                 init app                    //
/////////////////////////////////////////////////
const app = express();
const config = Object.freeze({
  port: process.env.APP_PORT || 3000,
  enableCors: true,
  prefix: "/api",
  success(res, data = null) {
    res.json({
      success: true,
      msg: "success",
      data,
    });
  },
  error(res, data = null) {
    res.json({
      success: false,
      msg: "error",
      data,
    });
  },
});

// parse request body
app.use(express.json({ extended: true }));

// enable cors requests
if (config.enableCors) {
  app.use(cors());
}

/////////////////////////////////////////////////
//                  routes                     //
/////////////////////////////////////////////////
const { success, error } = config;
app.get("/", (_, res) => success(res, "OK"));
app.get("/articles", (_, res) => {
  const articles = mock({
    page: 1,
    size: 10,
    "rows|10": [
      {
        id: "@id",
        title: "@ctitle",
        contents: "@cparagraph",
      },
    ],
  });

  success(res, articles);
});

// for post example
app.post("/login", (_, res) => {
  success(res, {
    token: "mock-token-string",
  });
});

// for patch/put example
app.patch("/article/:id", (req, res) => {
  success(res, {
    id: req.params.id,
  });
});

// for delete example
app.delete("/article/:id", (req, res) => {
  success(res, {
    id: req.params.id,
  });
});

// get env variables for test pm2 config
app.get("/env", (_, res) => {
  success(res, {
    app_port: process.env.APP_PORT,
    node_env: process.env.NODE_ENV,
    timezone: process.env.TZ,
    env: process.env,
  });
});

// global error handler
app.use((err, _req, res, _next) => {
  console.error("🤡[ ERROR ]:", err);
  return error(res, {
    message: err.message || "Internal Server Error",
    stack: process.env.NODE_ENV === "development" ? err.stack : undefined,
  });
});

/////////////////////////////////////////////////
//                  listen                     //
/////////////////////////////////////////////////
app.listen(config.port, () => {
  const url = `http://localhost:${config.port}`;
  console.log(`server started on: ${url}`);
});

Released under the MIT License.