Windows系统使用docker部署项目(有网与离线)
Docker 默认拉取的镜像版本与宿主机 CPU 架构一致,例如在 x86 架构主机上默认拉取 x86 镜像,在 ARM64 架构主机(如树莓派)上默认拉取 ARM64 镜像。若需跨平台拉取镜像,需显式指定目标架构参数。
前提:在 Windows 系统上安装 Docker Desktop 是最简单的方式,它集成了 Docker 引擎、Docker Compose、Kubernetes 等组件,并支持 WSL 2 或 Hyper-V 作为后端。
参考:Docker安装和使用入门保姆级教程)
配置好镜像,不然接下来很多操作都进行不了。
一、docker相关命令
1、查看镜像
命令:docker images
或 docker image ls
示例:列出所有镜像(含ID、仓库、标签、大小)
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"
2、拉取镜像
基础命令:docker pull [仓库名]:[标签]
示例:拉取MySQL 8.0.35镜像
docker pull mysql:8.0.35
建议:显式声明版本标签,避免依赖默认的latest(可能引发版本冲突)。
3、删除镜像
按标签删除:docker rmi mysql:8.0.11
按ID删除:docker rmi 5dbe5b6313e1
清理悬空镜像:docker image prune
删除所有容器:
4、搜索镜像
基础搜索:docker search httpd
过滤官方镜像:docker search --filter "is-official=true" nginx
5、查看镜像详情
元数据:docker inspect mysql:8.0.35
构建历史:docker history mysql:8.0.35
二、确认当前环境架构
(1)检查宿主机架构(Windows 通常为 amd64):
docker system info --format '{{.Architecture}}'
若输出 x86_64 或 amd64,表示宿主机是 x86 架构。
或者
docker buildx ls
此处的输出已显示支持 linux/amd64。
前提:之前在x86使用buildx构建arm64镜像,现在需要构建x86镜像,在切换架构(从 ARM64 回退到 X86)构建镜像时,必须明确确认当前 Docker Buildx 的构建环境配置,否则可能会因架构不匹配导致镜像无法运行或性能问题。
当前激活的是 multiarch(星号 * 标记),可通过 docker buildx use default 切换。
三、拉取 x86 镜像的 3 种方法
方法 1:直接拉取(默认行为)
适用场景:宿主机是 x86 时,直接拉取镜像默认就是 x86 版本。
docker pull ubuntu:22.04 # 自动匹配宿主机架构(x86)
方法 2:显式指定 --platform=linux/amd64
适用场景:强制拉取 x86 镜像(即使宿主机是 ARM 或跨平台构建)。
docker pull --platform=linux/amd64 ubuntu:22.04
方法 3:通过 Buildx 创建多架构镜像(高级)
适用场景:需要同时构建/拉取多架构镜像(如 x86 + ARM)。
# 1. 创建自定义 Buildx 构建器(若未创建)
docker buildx create --name mybuilder --use
docker buildx inspect --bootstrap# 2. 拉取 x86 镜像(通过 Buildx)
docker buildx build --platform=linux/amd64 -t my-ubuntu:amd64 --load .
# 或直接拉取
docker buildx pull --platform=linux/amd64 ubuntu:22.04
四、Docker 会自动拉取镜像
直接运行命令时:Docker 会自动拉取镜像
例如:下载redis镜像
docker run --name my-redis -d redis
检查本地是否存在 redis 镜像(通过 docker images
查看)。
(1)问题:
报错:Unable to find image ‘redis:latest’ locally
docker: Error response from daemon: failed to resolve reference “docker.io/library/redis:latest”: failed to do request: Head “https://registry-1.docker.io/v2/library/redis/manifests/latest”: dialing registry-1.docker.io:443 container via direct connection because static system has no HTTPS proxy: connecting to registry-1.docker.io:443: dial tcp 157.240.15.8:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
Run ‘docker run --help’ for more information
(2)测试:
①测试能否访问 Docker Hub:ping registry-1.docker.io
或者
②尝试用浏览器访问https://registry-1.docker.io/v2/,看是否能连接(可能返回 401 Unauthorized,但能连接即正常)。
(3)原因:
网络连接问题:Docker 默认会从 Docker Hub(registry-1.docker.io)拉取镜像,但网络不能否访问 Docker Hub。
(3)解决:因为一开始没有配置 Docker 国内镜像源
五、Windows系统使用docker部署项目(有网)
确保 Docker Desktop 已启动(任务栏有鲸鱼图标)
补充:
①NAMES 列:始终是容器名称(由 --name 指定或随机生成)。
IMAGE 列:才是镜像名称(如 openjdk:8)。
②docker restart 用于重启一个或多个已停止或正在运行的容器。它的操作对象是容器名(Container Name)或容器 ID(Container ID)。
步骤一、创建自定义网络
使用docker部署(所有容器都在同一个网络里):
创建自定义网络(网络名:my-network)
docker network create my-network
步骤二、创建Redis容器
(1)运行 Redis 容器:
docker run --name redis --network my-network -p 6379:6379 -d redis
①首次运行 Mysql 容器时,本地没有缓存 Mysql 镜像,Docker 会尝试从 Docker Hub 下载。
②检查后端 Redis 配置:确保 application.yml 中 Redis 配置正确:
spring.redis.host=redis # 使用在docker里的容器名
spring.redis.port=6379
(2)验证运行状态:
检查redis是否有错误日志
docker logs redis
步骤三、创建Mysql容器
(1)运行 Mysql 容器:
docker run --name mysql --network my-network -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
①端口冲突:3306 端口已被占用(可能是本地 MySQL 服务或其他容器)。
修改 Docker 映射的端口
将容器的 3306 端口映射到主机的其他端口(如 3307):
docker run --name mysql --network my-network -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
②移除多余的容器id:1ee58cc736e3
docker rm 1ee58cc736e3
查看所有容器
docker ps -a
(2)验证运行状态:
检查mysql是否有错误日志
docker logs mysql
步骤四、创建Java8容器
注意:Docker 在 Linux/WSL 环境下通过 /mnt/ 访问 Windows 磁盘(如 E: → /mnt/e)。
(1)运行 Java8 容器:
test-0.0.1-SNAPSHOT.jar 位于 Windows 目录 E:\project\postgresq\back\target。
docker run -d --name java8 --network my-network -v E:/project/postgresq/back/target:/app openjdk:8 java -jar /app/test-0.0.1-SNAPSHOT.jar
E:/project/postgresq/back/target:主机(Windows)上的目录路径。
/app:容器内部的目录路径。
作用:
将主机上的 E:/project/postgresq/back/target 目录挂载到容器的 /app 目录,使得容器内的进程可以访问主机上的文件。
(2)验证运行状态:
实时查看日志,查看控制台有没有报错
docker logs -f java8
步骤五、创建Nginx容器
(1)运行Nginx容器:
D:\data下:dist前端打包文件与nginx.conf配置文件
docker run -d --name nginx --network my-network -p 8085:82 -v "D:/data/dist:/usr/share/nginx/html/dist" -v "D:/data/nginx.conf:/etc/nginx/conf.d/default.conf" nginx
docker run -d \--name nginx \ # 容器名称--network my-network \ # 加入自定义 Docker 网络-p 8085:82 \ # 端口映射(宿主机:容器)-v "D:\data\dist:/usr/share/nginx/html/dist" \ # 挂载静态文件目录-v "D:\data\nginx.conf:/etc/nginx/conf.d/default.conf" \ # 挂载自定义 Nginx 配置nginx # 使用官方 Nginx 镜像
(2)新建nginx.conf
nginx.conf配置文件:
server {
listen 82;
server_name localhost;location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}location /api/ {
proxy_pass http://java8:8084/test/;
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 /usr/share/nginx/html;
}
}
关键点总结:
(1)前后端分离:
前端静态文件:通过 root 指向 /dist 目录(通常由 Vue/React 构建生成)。
后端 API:通过 /api/ 代理到 java8 容器的 8084 端口(路径重写为 /test/)。
(2)前端路由支持:
try_files $uri $uri/ /index.html 确保单页应用(SPA)的路由在刷新时仍返回 index.html,由前端框架处理路由。
(3)代理配置:
proxy_pass 的目标地址是 Docker 内部容器名 java8(需确保容器在同一个 Docker 网络 my-network 中)。
传递了客户端 IP 和原始 Host,便于后端服务记录日志或鉴权。
(4)端口与路径:
Nginx 监听 82 端口,需在 Docker 映射时暴露(如-p 8085:82)。
API 路径被重写:/api/xxx → http://java8:8084/test/xxx。
补充:
- 基础配置
server {listen 82; # 监听 82 端口server_name localhost; # 服务器名称(本地回环地址)
listen 82:Nginx 监听 82 端口(非默认的 80 端口,为了避免冲突或特定需求)。
server_name localhost:匹配请求头中的 Host 为 localhost(仅本地访问)。
- 静态文件服务(前端路由)
location / {root /usr/share/nginx/html/dist; # 静态文件根目录index index.html index.htm; # 默认首页文件try_files $uri $uri/ /index.html; # 前端路由 fallback
}
location /:匹配所有请求路径(根路径及其子路径)。
root:静态文件(如 HTML、JS、CSS)存放在容器的 /usr/share/nginx/html/dist 目录。
index:优先返回 index.html 或 index.htm。
try_files:
按顺序检查 $uri(请求的文件)和 $uri/(目录)是否存在。
如果都不存在,则返回 /index.html(关键:支持前端路由,如 Vue/React 的 History 模式)。
- API 请求代理(后端路由)
location /api/ {proxy_pass http://java8:8084/test/; # 代理到后端服务proxy_set_header Host $host; # 传递原始请求头proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递代理链 IP
}
location /api/:匹配以 /api/ 开头的请求(如 /api/users)。
proxy_pass:将请求转发到 http://java8:8084/test/(java8 是 Docker 网络中的容器名)。
例如:/api/data → http://java8:8084/test/data。
proxy_set_header:
Host $host:保留原始请求的 Host 头。
X-Real-IP 和 X-Forwarded-For:用于后端获取客户端真实 IP(避免代理丢失)。
- 错误页面
error_page 500 502 503 504 /50x.html; # 定义错误码对应的页面
location = /50x.html {root /usr/share/nginx/html; # 错误页面路径
}
error_page:当服务器返回 500、502、503 或 504 错误时,显示 /50x.html。
location = /50x.html:精确匹配 /50x.html,从 /usr/share/nginx/html 加载文件。
(3)验证运行状态:
打开浏览器,访问 http://127.0.0.1:8085(因为docker使用映射-p 8085:82,所以是8085不是82)
五、Windows系统使用docker部署项目(离线)
在没有网络的环境下,由于 Docker 需要从 Docker Hub 拉取镜像,会因无法访问网络而失败。
步骤一、拉取镜像(在有网的机器上执行):
docker pull redis:latest
docker pull mysql:latest
docker pull openjdk:8
docker pull nginx:latest
步骤二、保存镜像为压缩包:
docker save -o redis.tar redis:latest
docker save -o mysql.tar mysql:latest
docker save -o openjdk8.tar openjdk:8
docker save -o nginx.tar nginx:latest
默认打包路径取决于你执行命令时所在的目录
步骤三、在离线机器上加载镜像:
docker load -i redis.tar
docker load -i mysql.tar
docker load -i openjdk8.tar
docker load -i D:\data\nginx.tar
验证镜像是否存在:
docker images | grep redis
docker images | grep mysql
docker images | grep openjdk
docker images | grep nginx
或直接docker images
查看所有镜像列表
步骤四、运行容器
(1)确保自定义网络 my-network 已存在:
如果之前未创建,需先创建:
docker network create my-network
(2)启动容器:
docker run --name redis --network my-network -p 6379:6379 -d redis
docker run --name mysql --network my-network -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
docker run -d --name java8 --network my-network -p 8084:8084 -v E:/project/postgresq/back/target:/app openjdk:8 java -jar /app/test-0.0.1-SNAPSHOT.jar
docker run -d --name nginx --network my-network -p 8085:82 -v "D:/data/dist:/usr/share/nginx/html/dist" -v "D:/data/nginx.conf:/etc/nginx/conf.d/default.conf" nginx
nginx配置文件参照上面
问题:
登陆的验证码刷新不显示,报错Failed to load resource: the server responded with a status of 502 (Bad Gateway)。但配置流程没有错误,过会儿后又能显示验证码。
因为后端数据库只能局域网访问,离线会因为数据库连接失败导致Java8容器运行后立刻停止。
六、部署多个项目
创建redis与MySQL容器参照上面不变
步骤一、创建多个java容器
例如test1-0.0.1-SNAPSHOT.jar与test2-0.0.1-SNAPSHOT.jar,创建容器java8Project1 与java8Project2。
docker run -d --name java8Project1 --network my-network -p 8083:8083 -v E:/project:/app openjdk:8 java -jar /app/test1-0.0.1-SNAPSHOT.jar
docker run -d --name java8Project2--network my-network -p 8084:8084 -v E:/project:/app openjdk:8 java -jar /app/test2-0.0.1-SNAPSHOT.jar
步骤二、创建nginx
端口根据不同项目映射不同端口
docker run -d --name nginx --network my-network -p 81:8081-p 82:8082-v "D:/data/dist:/usr/share/nginx/html/dist" -v "D:/data/nginx.conf:/etc/nginx/conf.d/default.conf" nginx
server {
listen 8081;
server_name localhost;location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}location /api/ {
proxy_pass http://java8Project1:8083/test1/;
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 /usr/share/nginx/html;
}
}server {
listen 8082;
server_name localhost;location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}location /api/ {
proxy_pass http://java8Project2:8084/test2/;
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 /usr/share/nginx/html;
}
}
打开浏览器,访问 http://127.0.0.1:81与 http://127.0.0.1:82