Docker 入门看这一篇就够了:从 0 到部署 Java 和 Node 项目实战

0 阅读9分钟

大家好,我是大华!

在后端和运维领域,Docker 几乎已经成了绕不开的技术。 面试在问,同事在用,越来越多的开源项目也默认提供了 Docker 一键部署方案。

那 Docker 到底解决了什么问题? 为什么现在的部署项目,大家都会优先选择它?

在这里插入图片描述

这篇文章,我想从一个新手的视角,把 Docker 讲清楚。

一、Docker是什么?

简单比喻

假设你要搬家:

  • 传统方式:家具要拆、线路要拔、到新家后再一件件装回去,装的时候还可能发现:少了某个零件、接口不对、怎么都摆不回原样。
  • Docker方式:直接把整个房间拍个快照,家具、布置、电器、位置全都封装好。到新家一键还原,跟原来一模一样。

Docker 做的,就是这件事。它把一个应用运行所需要的所有东西,代码、运行环境、依赖、配置,一次性打包成一个标准化的箱子。

在这里插入图片描述

不管你把这个箱子搬到哪里,只要能打开,它的表现永远一致。

专业解释

Docker是一个容器化平台,让开发者可以:

  • 把应用程序及其所有依赖项(库、环境变量、配置文件)打包在一起
  • 在任何支持 Docker 的机器上运行,保证环境一致
  • 从而实现一次构建,到处运行

二、Docker有什么用?

1. 开发人员的痛点

开发者小明说:“在我电脑上运行好好的!”
运维人员回复:“在服务器上就是跑不起来!”

原因排查:
- 操作系统不同(Windows vs Linux)
- Node.js版本不同(12.x vs 14.x)
- 依赖库版本冲突
- 环境变量配置不同
- 文件路径不一致

最后你会发现,问题不是代码,而是环境。

Docker 出现的意义,就是把环境这件事彻底消灭。

2. 快速部署

传统部署:装系统、装运行环境、配环境变量再到装依赖等等,顺利的话,也要一两个小时。

Docker部署:下载镜像、运行容器,几分钟就能完成。

3. 资源节省

很多人会拿 Docker 和虚拟机做对比。

虚拟机的方式:每个应用自带一整套操作系统,占用动不动就是几个 GB

Docker 的方式:容器之间共享宿主机系统,只保留应用真正需要的东西,通常是 MB 级别。

你可以理解为

  • 虚拟机:每个项目都自己买一套房
  • Docker:很多项目住在同一栋楼里,各自一间房

三、Docker 的四个核心概念

Docker 的核心概念其实非常少。

如果只用一句话来概括:Docker 用镜像准备环境,用容器运行程序。

在这里插入图片描述

1、镜像(Image)

镜像就是运行环境的模板。

它里面已经准备好了系统、运行时以及应用需要的依赖,但镜像本身是不能直接运行的,更像一个安装包。比如 node:18openjdk:17mysql:8,都是现成可以用的镜像。

2、容器(Container)

容器是镜像运行之后的样子。

镜像是静态的,容器是正在运行的。你平时对应用做的启动、停止、删除、查看日志,操作的其实都是容器。一个镜像可以同时启动多个容器,这也是 Docker 能跑多个实例的原因。

3、Dockerfile

Dockerfile 用来告诉 Docker,这个镜像该怎么做。

它是一个普通文本文件,里面写清楚:用什么基础镜像、代码放在哪里、要不要安装依赖,以及程序最终如何启动。想定制自己的镜像,就必须有 Dockerfile。

4、仓库(Docker Hub)

Docker Hub 是镜像的来源。

它就像一个应用商店,存放着大量官方和社区维护的镜像。

Dockerfile 里写的 FROM node:18,意思就是:从 Docker Hub 拉取一个 Node 18 的镜像作为基础环境。


把这几个概念串起来就是一句话:Dockerfile 用来构建镜像,镜像用来创建容器,而镜像通常来自 Docker Hub。

四、安装Docker(以 Ubuntu 为例)

下面以 Ubuntu 20.04 / 22.04 为例,介绍最常见、也是最稳妥的安装方式。

步骤 1:更新系统并安装基础依赖

sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

这些工具主要用来安全地添加 Docker 官方仓库。


步骤 2:添加 Docker 官方 GPG Key

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

步骤 3:添加 Docker 官方软件源

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

步骤 4:安装 Docker 引擎

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

步骤 5:验证是否安装成功

docker --version
sudo docker run hello-world

如果看到:

Hello from Docker!

说明 Docker 已经在你的 Ubuntu 服务器上成功运行。


(可选)步骤 6:非 root 用户运行 Docker

默认情况下,Docker 需要 sudo 权限。如果你不想每次都加 sudo,可以执行:

sudo usermod -aG docker $USER

然后 退出当前终端重新登录,再测试:

docker ps

能正常执行,说明配置成功。


五、常用的Docker命令

基础命令

# 查看版本
docker --version

# 查看所有命令
docker --help

# 查看运行中的容器
docker ps

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

# 查看本地镜像
docker images

# 下载镜像(从Docker Hub)
docker pull 镜像名:标签
# 示例:docker pull node:14

# 运行容器
docker run [选项] 镜像名
# 示例:docker run -it ubuntu bash

# 停止容器
docker stop 容器ID或名字

# 删除容器
docker rm 容器ID或名字

# 删除镜像
docker rmi 镜像ID或名字

常用选项

# -d:后台运行(守护进程模式)
docker run -d nginx

# -p:端口映射(主机端口:容器端口)
docker run -p 8080:80 nginx

# -v:挂载卷(主机目录:容器目录)
docker run -v /home/data:/app/data nginx

# --name:给容器起名字
docker run --name my_nginx nginx

# -it:交互模式运行
docker run -it ubuntu bash

六、部署Java项目(Spring Boot示例)


项目结构(Windows 本地)

my-java-app/
├── src/          # 源代码
├── pom.xml       # Maven 配置文件
└── Dockerfile    # Docker 构建文件

步骤1:编写 Dockerfile(Windows 本地)

在项目根目录下创建 Dockerfile

# 使用官方 Java 运行环境作为基础镜像
FROM openjdk:11-jre-slim

# 设置容器内工作目录
WORKDIR /app

# 复制 Spring Boot 打包后的 jar 文件
COPY target/myapp.jar app.jar

# 暴露端口(Spring Boot 默认 8080)
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]

⚠️ 注意: Dockerfile 中的路径是 容器内路径,和 Windows / Linux 本机路径无关。


步骤2:Windows 本地打包项目

Windows 本地开发环境 执行:

# 进入项目目录
cd my-java-app

# 使用 Maven 打包(生成 target/myapp.jar)
mvn clean package

执行完成后,确认文件存在:

target/myapp.jar

步骤3:将项目传到 Linux 服务器

方式一:使用 scp(推荐)

在 Windows 终端(PowerShell / Git Bash)中执行:

scp -r my-java-app user@服务器IP:/home/user/

示例:

scp -r my-java-app root@123.456.78.90:/root/

步骤4:Linux 服务器上构建 Docker 镜像

登录 Linux 服务器后执行:

cd my-java-app

构建镜像:

docker build -t my-java-app:1.0 .

查看镜像是否构建成功:

docker images

步骤5:在 Linux 上运行容器

docker run -d \
  -p 8080:8080 \
  --name java-app \
  my-java-app:1.0

查看容器状态:

docker ps

查看日志:

docker logs java-app

步骤6:访问应用

http://123.456.78.90:8080

七、部署Node.js项目(Express示例)

项目结构(Windows 本地)

my-node-app/
├── src/
├── package.json
├── server.js
└── Dockerfile

步骤1:编写 Dockerfile(Windows 本地)

在项目根目录创建 Dockerfile

# 使用官方 Node.js 运行环境
FROM node:18-alpine

# 设置容器工作目录
WORKDIR /app

# 复制依赖配置文件
COPY package*.json ./

# 安装依赖
RUN npm install --production

# 复制项目代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["node", "server.js"]

步骤2:将项目上传到 Linux 服务器

方式一:scp 传输(推荐)

在 Windows 终端执行:

scp -r my-node-app user@服务器IP:/home/user/

例如:

scp -r my-node-app root@123.456.78.90:/root/

步骤3:Linux 服务器构建镜像

登录 Linux 服务器:

cd my-node-app

构建镜像:

docker build -t my-node-app:1.0 .

查看镜像:

docker images

步骤4:运行容器

docker run -d \
  -p 3000:3000 \
  --name node-app \
  my-node-app:1.0

查看运行状态:

docker ps

查看日志:

docker logs node-app

步骤5:访问应用

http://服务器IP:3000

可选:多阶段构建优化版(推荐生产环境)

# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 运行阶段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

八、同时部署 Java + Node + MySQL

这里使用的是 Docker ComposeDocker Compose 是用一个配置文件,统一管理多个 Docker 容器的工具。

场景说明

服务器部署结构:

Linux服务器
 ├── MySQL
 ├── Spring Boot 后端
 └── Node 前端

步骤1:服务器准备目录结构

在 Linux 服务器创建:

project/
 ├── docker-compose.yml
 ├── java-backend/
 └── node-frontend/

把两个项目代码分别上传进去。


步骤2:创建 docker-compose.yml

version: '3.8'

services:

  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - app-network

  java-backend:
    build: ./java-backend
    container_name: java-backend
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb
      SPRING_DATASOURCE_USERNAME: user
      SPRING_DATASOURCE_PASSWORD: password
    depends_on:
      - mysql
    networks:
      - app-network

  node-frontend:
    build: ./node-frontend
    container_name: node-frontend
    ports:
      - "3000:3000"
    environment:
      API_URL: http://java-backend:8080
    depends_on:
      - java-backend
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  mysql-data:

步骤3:启动所有服务(Linux 服务器执行)

docker compose up -d

新版本 Docker 推荐 docker compose,老版本使用 docker-compose


查看运行状态:

docker compose ps

查看日志:

docker compose logs -f

停止服务:

docker compose down

步骤4:访问系统

node访问

http://服务器IP:3000

java访问

http://服务器IP:8080

MySQL 连接地址

服务器IP:3306

九、实用的几个常用命令

1. 进入运行中的容器

# 进入容器内的bash
docker exec -it 容器名 bash

# 在容器内执行命令
docker exec 容器名 ls /app

2. 查看容器资源使用

docker stats

3. 清理无用资源

# 删除所有停止的容器
docker container prune

# 删除所有未被使用的镜像
docker image prune

# 删除所有未被使用的网络
docker network prune

# 一键清理所有
docker system prune -a

4. 查看镜像构建历史

docker history 镜像名

5. 备份和恢复

# 备份镜像到文件
docker save -o myapp.tar myapp:1.0

# 从文件恢复镜像
docker load -i myapp.tar

写在最后

如果你是第一次接触 Docker,看到这里可能还是有点懵,这很正常。

等你哪天真的把一个项目从本地跑到服务器上,用 Docker 一次性拉起来的时候,那种终于搞定了的感觉,会非常明显。

本文首发于公众号:程序员大华,专注前端、Java开发,AI应用和工具的分享。关注我,少走弯路,一起进步!