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.npm.taobao.org

# 安装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 项目

仅 express 代码, 不包含链接数据库配置

txt
.
├── Dockerfile            # 构建镜像配置文件
├── README.md
├── app.js                # 服务端代码
├── docker-compose.yaml   # docker-compose 配置文件
├── package-lock.json     # 依赖管理文件
├── package.json          # 项目配置文件
└── public                # 静态文件目录
    └── upload
        └── 40a080a7-afe3-4e43-a4bf-f29f1ced2f1a.png

3 directories, 7 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}
ARG APP_HOST=http://localhost:3000
ENV APP_HOST=${APP_HOST}

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

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

# 使用腾讯 npm 镜像源 & 安装依赖
RUN npm config set registry https://mirrors.tencent.com/npm/
RUN npm install

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

# 执行启动命令, 需要在 package.json 中配置
CMD ["npm", "run", "start"]
yaml
services:
  app:
    image: express-api-demo # docker打包后的镜像名称
    build: .
    volumes:
      # 映射容器中的目录(注意当前目录下的 public 目录必须存在, 否则可能报错)
      - ./public:/app/public
    ports:
      # 端口映射(宿主机端口:容器端口)
      - 8000:3000
    environment:
      # 环境变量控制
      - NODE_ENV=production
      - APP_HOST=http://localhost:8000
js
import express from "express";
import cors from "cors";
import multer from "multer";
import path from "node:path";
import fs from "node:fs";
import { v4 as uuidv4 } from "uuid";

// setup express app
const app = express();
const port = 3000;
const host = process.env.APP_HOST || `http://localhost:${port}`;
const publicDir = "public";
const uploadDir = "upload";
app.set("app_host", host);
app.set("publicDir", publicDir);
app.set("uploadDir", uploadDir);
app.set("uploadPath", path.join(publicDir, uploadDir));

// middlewares
app.use(cors());
app.use(express.json());
app.use(express.static(publicDir));

// helper functions
function mkdirIfNotExists(dir) {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

// format response body struct
app.use((_req, res, next) => {
  res.success = function (results = null, message = "success") {
    return res.json({
      success: true,
      results,
      message,
    });
  };

  res.failed = function (results = null, message = "failed") {
    return res.json({
      success: false,
      results,
      message,
    });
  };

  return next();
});

///////////////////////////////////////////////////
// check health api
///////////////////////////////////////////////////
app.get("/", (_req, res) => res.success());

///////////////////////////////////////////////////
// upload file api
///////////////////////////////////////////////////
const storage = multer.diskStorage({
  filename(_req, file, callback) {
    const filename = uuidv4();
    const extname = path.extname(file.originalname);
    callback(null, `${filename}${extname}`);
  },
  destination(req, _file, callback) {
    const savePath = req.app.get("uploadPath");
    mkdirIfNotExists(savePath);
    callback(null, savePath);
  },
});
app.post("/upload", multer({ storage }).single("file"), (req, res) => {
  const filePath = path.join(req.app.get("uploadDir"), req.file.filename);
  const fileURL = [app.get("app_host"), "/", filePath].join("");

  res.success({
    filePath,
    fileURL,
  });
});

// global error handler
app.use((err, _req, res, _next) => res.failed(err.message));

// listen
app.listen(port, () => console.log(`>>>Server started on ${host}`));
json
{
  "name": "express-api-demo",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "node ./app.js"
  },
  "dependencies": {
    "cors": "2.8.5",
    "express": "5.0.1",
    "multer": "1.4.5-lts.1",
    "uuid": "11.0.3"
  }
}

Released under the MIT License.