在 macOS 上用 Docker 为 Java 后端 常见开发需求搭建完整服务(详尽教程)
说明:本文假设你在 macOS(Intel 或 Apple Silicon)上使用 Docker Desktop。如果你已经安装 Docker,请从“创建 compose 文件”那一节直接开始。
目录(快速导航)
- 安装 Docker Desktop(macOS)
- Docker Desktop 基本配置建议(资源、端口、文件共享)
- 推荐服务清单(为 Java 后端与通用开发)
- 为所有服务准备的
docker-compose.yml
(完整示例) - 启动 / 停止 / 管理容器的常用命令
- 每个服务的详细说明、配置与注意事项(MySQL / PostgreSQL / Redis / Elasticsearch + Kibana / RabbitMQ / Nginx / Jenkins / Gitea / MinIO / Prometheus + Grafana / Portainer / Node)
- Spring Boot(Java 后端)连接示例配置
- 数据卷、备份与恢复(MySQL、Postgres、Elasticsearch 等)
- 常见问题与排查方法
- 安全、性能与生产提醒
1. 安装 Docker Desktop(macOS)——一步步来
-
访问 Docker 官网下载适合你 Mac 的 Docker Desktop 安装包(Apple Silicon / Intel)。
- 在浏览器输入
docker desktop mac
即可找到下载页面(注意选对 CPU 架构)。
- 在浏览器输入
-
下载完成后,双击
.dmg
,把 Docker.app 拖到Applications
文件夹。 -
打开
Applications
中的 Docker.app,第一次启动会要求输入系统密码(以允许安装虚拟化工具)。 -
启动后菜单栏会出现小鲸鱼图标,等待 “Docker is running”。
-
(可选)登录 Docker Hub 账号以便拉取私有镜像或速率更高。
提示:Apple Silicon(M1/M2)与 Intel 镜像的差异:优先使用
:alpine
或多平台镜像(多数官方镜像支持 multi-arch)。如果镜像只支持 amd64,Docker Desktop 会自动使用仿真(QEMU),但会慢一些。
2. Docker Desktop 基本配置(很重要)
打开 Docker Desktop → Preferences(偏好):
-
Resources(资源):给 Docker 分配足够资源(尤其是运行 Elasticsearch、Jenkins、Postgres 时)
- CPU: 4 cores 或更多(视主机而定)
- Memory: 8GB 起(如果跑 ES + Kibana 建议 12GB)
- Swap: 1–2GB
-
File sharing / Volumes:确保你的项目目录(比如
~/projects
或~/workspace
)已被允许共享给 Docker。 -
Network:默认即可,一般无需修改。
3. 推荐服务清单(针对 Java 后端 + 常见需求)
- 必备(Java 后端常用):MySQL / PostgreSQL、Redis、Nginx(反向代理)、RabbitMQ、Elasticsearch + Kibana、MinIO(S3 存储模拟)
- CI / 管理:Jenkins、Gitea(轻量 Git 服务)、Portainer(Docker 管理 UI)
- 监控 / 日志:Prometheus + Grafana、Loki(可选)
- 辅助:Node 镜像(前端构建)、MailHog(邮件捕获,开发环境)
4. 一份完整的 docker-compose.yml
(示例)
下面是一个功能齐全但尽量通用的 docker-compose.yml
,包含 MySQL、Postgres、Redis、Elasticsearch + Kibana、RabbitMQ、MinIO、Nginx、Jenkins、Gitea、Prometheus、Grafana、Portainer。把它放在一个目录下(例如 ~/docker-dev
),文件名 docker-compose.yml
。
version: '3.8'services:# MySQLmysql:image: mysql:8.0container_name: mysqlenvironment:MYSQL_ROOT_PASSWORD: rootpasswordMYSQL_DATABASE: demoMYSQL_USER: demoMYSQL_PASSWORD: demopassvolumes:- mysql_data:/var/lib/mysql- ./mysql/init:/docker-entrypoint-initdb.d # 可放初始化 SQLports:- "3306:3306"healthcheck:test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]interval: 10stimeout: 5sretries: 5# PostgreSQLpostgres:image: postgres:15container_name: postgresenvironment:POSTGRES_USER: demoPOSTGRES_PASSWORD: demopassPOSTGRES_DB: demovolumes:- pg_data:/var/lib/postgresql/dataports:- "5432:5432"# Redisredis:image: redis:7-alpinecontainer_name: redisports:- "6379:6379"volumes:- redis_data:/data# Elasticsearch (适合开发,生产请更谨慎)elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.14.0container_name: elasticsearchenvironment:- discovery.type=single-node- "ES_JAVA_OPTS=-Xms1g -Xmx1g"- xpack.security.enabled=falseulimits:memlock:soft: -1hard: -1volumes:- es_data:/usr/share/elasticsearch/dataports:- "9200:9200"- "9300:9300"healthcheck:test: ["CMD-SHELL", "curl -sS http://localhost:9200/_cluster/health | grep -q '\"status\"'"]interval: 20stimeout: 10sretries: 10# Kibanakibana:image: docker.elastic.co/kibana/kibana:8.14.0container_name: kibanaenvironment:ELASTICSEARCH_HOSTS: 'http://elasticsearch:9200'ports:- "5601:5601"depends_on:- elasticsearch# RabbitMQrabbitmq:image: rabbitmq:3.10-managementcontainer_name: rabbitmqports:- "5672:5672"- "15672:15672"volumes:- rabbitmq_data:/var/lib/rabbitmq# MinIO (S3 仿真)minio:image: minio/miniocontainer_name: minioenvironment:MINIO_ROOT_USER: minioMINIO_ROOT_PASSWORD: minio123command: server /dataports:- "9000:9000"- "9001:9001" # 控制台(新版)volumes:- minio_data:/data# Jenkinsjenkins:image: jenkins/jenkins:lts-jdk11container_name: jenkinsuser: rootenvironment:JAVA_OPTS: "-Djenkins.install.runSetupWizard=false"volumes:- jenkins_home:/var/jenkins_homeports:- "8080:8080"- "50000:50000"# Gitea (轻量的 Git 服务)gitea:image: gitea/gitea:latestcontainer_name: giteaenvironment:USER_UID: 1000USER_GID: 1000volumes:- gitea_data:/dataports:- "3000:3000"- "222:22"# Nginx (作为静态/反向代理)nginx:image: nginx:latestcontainer_name: nginxvolumes:- ./nginx/conf.d:/etc/nginx/conf.d:roports:- "80:80"- "443:443"depends_on:- jenkins# Prometheusprometheus:image: prom/prometheus:latestcontainer_name: prometheusvolumes:- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:roports:- "9090:9090"# Grafanagrafana:image: grafana/grafana:latestcontainer_name: grafanaports:- "3001:3000"volumes:- grafana_data:/var/lib/grafana# Portainer (Docker 管理 UI)portainer:image: portainer/portainer-ce:latestcontainer_name: portainercommand: -H unix:///var/run/docker.sockvolumes:- /var/run/docker.sock:/var/run/docker.sock- portainer_data:/dataports:- "9002:9000"volumes:mysql_data:pg_data:redis_data:es_data:rabbitmq_data:minio_data:jenkins_home:gitea_data:grafana_data:portainer_data:
说明:
- 把以上
docker-compose.yml
放在~/docker-dev
(示例路径)。- 你可以把敏感密码放在
.env
文件里(更安全),并用${VAR}
在 Compose 文件中引用。
5. 启动 / 停止 / 查看日志(常用命令)
在 docker-compose.yml
所在目录执行:
- 启动(后台):
docker compose up -d
- 查看容器状态:
docker compose ps
- 查看某个服务日志(实时):
docker compose logs -f mysql
# 或者 docker logs -f mysql
- 停止并移除容器(保留数据卷):
docker compose down
- 停止并移除容器及数据卷(小心!会删除数据):
docker compose down -v
- 进入正在运行的容器(调试):
docker exec -it mysql bash
# 如果容器没有 bash,使用 sh
6. 每个服务的详细配置、注意事项与技巧
下面逐个讲解常用服务的要点、如何与 Java/Spring Boot 连接,以及常见坑。
MySQL(开发)
- 镜像:
mysql:8.0
- 端口:
3306
- 数据持久化:使用 Docker 卷(上例
mysql_data
) - 初始化脚本:把
.sql
放到./mysql/init
,容器首次启动时会执行(官方 entrypoint 逻辑)。 - JDBC 示例(Spring Boot application.properties):
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username=demo
spring.datasource.password=demopass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
- 连接问题:若从 macOS 本机用
localhost:3306
连接有效(因为ports: "3306:3306"
做了映射)。如果使用 Docker 网络内其他服务,使用mysql:3306
(服务名)作为主机名。
PostgreSQL
- 镜像:
postgres:15
- 端口:
5432
- JDBC 示例:
spring.datasource.url=jdbc:postgresql://localhost:5432/demo
spring.datasource.username=demo
spring.datasource.password=demopass
Redis
- 镜像:
redis:7-alpine
- 端口:
6379
- Spring Boot 配置:
spring.redis.host=localhost
spring.redis.port=6379
Elasticsearch + Kibana(注意内存与兼容)
-
镜像:
docker.elastic.co/elasticsearch/elasticsearch:8.x
-
要求:
- ES 通常需要较多内存(设置
ES_JAVA_OPTS
,例如-Xms1g -Xmx1g
)。 - 在 Linux 上常需设置
vm.max_map_count=262144
。在 macOS 上 Docker Desktop 使用内置 Linux VM,通常不需要用户手动设置;如果遇到错误,重启 Docker Desktop 或查看官方文档。
- ES 通常需要较多内存(设置
-
访问:
http://localhost:9200
(ES)和http://localhost:5601
(Kibana)。 -
Spring Data Elasticsearch:使用
http://localhost:9200
作为主机;对于 Spring Boot 3 / recent ES 客户端,查看对应版本兼容性。
RabbitMQ
- 镜像:
rabbitmq:3.10-management
- 管理界面:
http://localhost:15672
(默认 guest/guest,compose 示例没有修改) - Spring Boot 配置:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
MinIO(S3 仿真)
- 镜像:
minio/minio
- 访问:
http://localhost:9000
(控制台 9001) - SDK:遵从 AWS S3 API(访问 key、secret 保存在环境变量中)
- 创建 bucket:可以在控制台或 MinIO 客户端
mc
创建。
Jenkins
- 镜像:
jenkins/jenkins:lts-jdk11
- 数据目录:映射到
jenkins_home
卷 - 访问:
http://localhost:8080
- 第一次启动:如关闭了 setup wizard,可在镜像里配置 admin 密码。若开启,按提示获取初始管理员密码(在
jenkins_home/secrets/initialAdminPassword
)。
Gitea(轻量 Git 服务)
- 访问:
http://localhost:3000
- SSH:
222
映射到容器的22
(用于 git+ssh)
Nginx
- 用途:本地反向代理、模拟生产环境部署、托管静态资源
- 配置:把
./nginx/conf.d
映射到/etc/nginx/conf.d
,可以写site.conf
来反代到你的 Spring Boot(http://backend:8080
)或前端静态文件。 - 示例反向代理:
server {listen 80;server_name localhost;location / {proxy_pass http://jenkins:8080; # 举例proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}
}
Prometheus + Grafana
-
Prometheus 用于采集指标(抓
/actuator/prometheus
),Grafana 用于展示。 -
在 Spring Boot 项目中:
- 引入
micrometer-registry-prometheus
- 启用
management.endpoint.prometheus.enabled=true
,暴露端点/actuator/prometheus
- 引入
-
Prometheus 配置文件示例(
prometheus.yml
):
global:scrape_interval: 15sscrape_configs:- job_name: 'spring'static_configs:- targets: ['host.docker.internal:9000'] # 示例:host.docker.internal 用于宿主机访问
注意:
host.docker.internal
在 Docker Desktop (mac) 上可用于容器访问宿主机服务;反过来宿主机访问容器用localhost:端口映射
。
Portainer(可视化管理 Docker)
- 访问:
http://localhost:9002
- 便于查看容器、卷、镜像、日志。
7. Spring Boot(Java 后端)连接示例(完整)
假设 Spring Boot 应用运行在本机(或容器外)并要连接上面服务。
application-dev.properties
(示例):
# MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=demo
spring.datasource.password=demopass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# Redis
spring.redis.host=localhost
spring.redis.port=6379# RabbitMQ
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest# Elasticsearch (示例)
spring.elasticsearch.uris=http://localhost:9200# Actuator Prometheus
management.endpoints.web.exposure.include=health,info,prometheus
management.endpoint.prometheus.enabled=true
management.metrics.export.prometheus.enabled=true
如果你的 Spring Boot 也放进 Docker(和上面的服务放在同一 docker-compose
),localhost
应改为服务名(例如 mysql:3306
);示例:
# docker-compose 中 app 服务示例
app:image: your-springboot-image:latestenvironment:- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/demo?useSSL=false&serverTimezone=UTCdepends_on:- mysql- redis
8. 数据卷、备份与恢复(关键)
MySQL 备份(导出 SQL)
docker exec -it mysql sh -c 'exec mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" demo' > demo.sql
恢复
cat demo.sql | docker exec -i mysql sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" demo'
PostgreSQL 备份
docker exec -t postgres pg_dumpall -c -U demo > dump.sql
Elasticsearch 快照(production 推荐)
- 在生产环境使用 snapshot to repository(例如文件系统或 S3)。开发环境若只是数据可重建,也可直接删除卷重建索引。
卷查看与清理
- 列出卷:
docker volume ls
- 删除未使用卷(谨慎):
docker volume prune
9. 常见问题与排查
-
容器启动失败 / CrashLoop
- 看日志:
docker compose logs -f 服务名
- 常见原因:端口冲突、环境变量缺失、数据目录权限
- 看日志:
-
Elasticsearch 报
max_map_count
错误- 在 Linux 上执行
sudo sysctl -w vm.max_map_count=262144
。 - 在 macOS Docker Desktop 下通常不需要;若出现,重启 Docker Desktop 并查看日志或官方文档。
- 在 Linux 上执行
-
连接失败(从宿主机到容器)
- 确认
ports
已映射(3306:3306
)。 - 使用
docker compose ps
检查端口映射。 - 宿主机用于连接容器应使用
localhost:端口
。
- 确认
-
数据丢失
- 启动时如果没有使用
volumes
而用bind mount
,注意宿主机目录权限与 SELinux(Linux)问题。 - 生产环境务必使用 Volume + 备份策略。
- 启动时如果没有使用
-
镜像拉取失败 / 速率限
- 登录 Docker Hub 或使用公司私有镜像仓库。
10. 安全、性能与生产提醒(重点)
- 不要在生产环境把敏感密码直接写在
docker-compose.yml
中,使用环境变量管理或 secrets(Docker Swarm / Kubernetes secrets)。 - 生产部署建议使用 Kubernetes(K8s)或托管服务而不是 Docker Compose。
- 数据库与 ES 的内存配置要按实际机器尺寸调整(
ES_JAVA_OPTS
、Postgres 的shared_buffers
等)。 - 对外暴露管理端口(如 Jenkins、Gitea、Kibana)时,记得加认证与防火墙规则。
- 镜像版本请固定(不要使用
latest
在生产),确保可复现部署。
11. 额外小技巧(提高效率)
-
用
.env
文件管理密码:MYSQL_ROOT_PASSWORD=rootpassword MYSQL_USER=demo MYSQL_PASSWORD=demopass
并在 compose 用
${MYSQL_PASSWORD}
引用。 -
使用
docker-compose.override.yml
来覆盖开发/测试环境配置。 -
用
docker-compose up --build
来强制 rebuild 本地镜像。 -
使用
host.docker.internal
(mac)让容器访问宿主机服务(例如本机运行的 IDE 服务)。
12. 一个快速可运行的入门流程(从零到有)
-
安装 Docker Desktop(见第1节)
-
在
~/docker-dev
创建docker-compose.yml
(使用上面的示例或精简版本) -
进入目录,启动:
cd ~/docker-dev docker compose up -d
-
看各服务状态:
docker compose ps
-
打开浏览器访问:
- MySQL: 用数据库客户端(DataGrip / DBeaver)连接
localhost:3306
- Jenkins:
http://localhost:8080
- Gitea:
http://localhost:3000
- Kibana:
http://localhost:5601
- Elasticsearch:
http://localhost:9200
- MinIO:
http://localhost:9000
- Grafana:
http://localhost:3001
- Portainer:
http://localhost:9002
- MySQL: 用数据库客户端(DataGrip / DBeaver)连接
-
在 Spring Boot 中配置
application.properties
指向localhost:3306
等。
13. 常见场景示例(快速片段)
- 把 Spring Boot 也放进 Compose(和 DB 同网段)
app:build: ./appimage: my-spring-appdepends_on:- mysql- redisenvironment:SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/demoSPRING_DATASOURCE_USERNAME: demoSPRING_DATASOURCE_PASSWORD: demopassports:- "8081:8080"
- 通过 IntelliJ 远程调试容器内的 Java 应用:启动 JVM 时加入
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
并在 compose 映射5005
端口。