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

大家好,我是大华!

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

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

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

一、Docker是什么?

简单比喻

假设你要搬家:

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

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

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

专业解释

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

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

二、Docker有什么用?

1. 开发人员的痛点

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

原因排查:
- 操作系统不同(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:更新系统并安装基础依赖

bash 复制代码
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

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


步骤 2:添加 Docker 官方 GPG Key

bash 复制代码
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 官方软件源

bash 复制代码
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 引擎

bash 复制代码
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

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

bash 复制代码
docker --version
sudo docker run hello-world

如果看到:

csharp 复制代码
Hello from Docker!

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


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

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

bash 复制代码
sudo usermod -aG docker $USER

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

bash 复制代码
docker ps

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


五、常用的Docker命令

基础命令

bash 复制代码
# 查看版本
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或名字

常用选项

bash 复制代码
# -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 本地)

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

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

在项目根目录下创建 Dockerfile

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 本地开发环境 执行:

bash 复制代码
# 进入项目目录
cd my-java-app

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

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

text 复制代码
target/myapp.jar

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

方式一:使用 scp(推荐)

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

bash 复制代码
scp -r my-java-app user@服务器IP:/home/user/

示例:

bash 复制代码
scp -r my-java-app root@123.456.78.90:/root/

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

登录 Linux 服务器后执行:

bash 复制代码
cd my-java-app

构建镜像:

bash 复制代码
docker build -t my-java-app:1.0 .

查看镜像是否构建成功:

bash 复制代码
docker images

步骤5:在 Linux 上运行容器

bash 复制代码
docker run -d \
  -p 8080:8080 \
  --name java-app \
  my-java-app:1.0

查看容器状态:

bash 复制代码
docker ps

查看日志:

bash 复制代码
docker logs java-app

步骤6:访问应用

text 复制代码
http://123.456.78.90:8080

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

项目结构(Windows 本地)

text 复制代码
my-node-app/
├── src/
├── package.json
├── server.js
└── Dockerfile

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

在项目根目录创建 Dockerfile

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 终端执行:

bash 复制代码
scp -r my-node-app user@服务器IP:/home/user/

例如:

bash 复制代码
scp -r my-node-app root@123.456.78.90:/root/

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

登录 Linux 服务器:

bash 复制代码
cd my-node-app

构建镜像:

bash 复制代码
docker build -t my-node-app:1.0 .

查看镜像:

bash 复制代码
docker images

步骤4:运行容器

bash 复制代码
docker run -d \
  -p 3000:3000 \
  --name node-app \
  my-node-app:1.0

查看运行状态:

bash 复制代码
docker ps

查看日志:

bash 复制代码
docker logs node-app

步骤5:访问应用

text 复制代码
http://服务器IP:3000

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

dockerfile 复制代码
# 构建阶段
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 服务器创建:

bash 复制代码
project/
 ├── docker-compose.yml
 ├── java-backend/
 └── node-frontend/

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


步骤2:创建 docker-compose.yml

yaml 复制代码
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 服务器执行)

bash 复制代码
docker compose up -d

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


查看运行状态:

bash 复制代码
docker compose ps

查看日志:

bash 复制代码
docker compose logs -f

停止服务:

bash 复制代码
docker compose down

步骤4:访问系统

node访问

text 复制代码
http://服务器IP:3000

java访问

text 复制代码
http://服务器IP:8080

MySQL 连接地址

text 复制代码
服务器IP:3306

九、实用的几个常用命令

1. 进入运行中的容器

bash 复制代码
# 进入容器内的bash
docker exec -it 容器名 bash

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

2. 查看容器资源使用

bash 复制代码
docker stats

3. 清理无用资源

bash 复制代码
# 删除所有停止的容器
docker container prune

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

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

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

4. 查看镜像构建历史

bash 复制代码
docker history 镜像名

5. 备份和恢复

bash 复制代码
# 备份镜像到文件
docker save -o myapp.tar myapp:1.0

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

写在最后

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

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

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

相关推荐
青云计划8 小时前
知光项目知文发布模块
java·后端·spring·mybatis
Victor3569 小时前
MongoDB(9)什么是MongoDB的副本集(Replica Set)?
后端
Victor3569 小时前
MongoDB(8)什么是聚合(Aggregation)?
后端
小锋学长生活大爆炸10 小时前
【教程】免Root在Termux上安装Docker
运维·docker·容器
进击切图仔10 小时前
常用 Docker 命令备份
运维·docker·容器
yeyeye11110 小时前
Spring Cloud Data Flow 简介
后端·spring·spring cloud
Tony Bai11 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
+VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序猿阿伟11 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
小小张说故事11 小时前
SQLAlchemy 技术入门指南
后端·python