
1. 初识 Docker核心考点Docker 解决啥、和虚拟机的区别、架构三件套解决啥大型项目组件多MySQL/Redis/RabbitMQ…依赖版本冲突 操作系统差异 → Docker 把应用依赖运行环境打包成镜像一次构建到处跑和虚拟机区别面试高频虚拟机Hypervisor 完整 Guest OS重、启动慢Docker共享宿主机内核只隔离进程轻量秒级启动架构三件套镜像 Image只读模板类比类容器 Container镜像跑起来的实例类比对象RegistryDockerHub / 阿里云 ACR / 私有 harbor存镜像的地方 面试被问Docker 为啥比 VM 轻答共享内核 无 Guest OS 就够别扯 cgroup/namespace 太细除非对方追问。2. 镜像加速镜像加速本质改/etc/docker/daemon.json的registry-mirrors2026还能正常访问的 { registry-mirrors: [ https://docker.1ms.run, https://docker.xuanyuan.me, https://docker.m.daocloud.io ] } 3. Docker 基本操作常用命令# 镜像管理 # 列出本地镜像 docker images # 拉取镜像 docker pull nginx:1.20 # 删除镜像 docker rmi nginx:1.20 # 导出镜像为tar文件 docker save -o nginx.tar nginx:1.20 # 从tar文件导入镜像 docker load -i nginx.tar # 查看镜像历史分层 docker history nginx:1.20 # 标记镜像打标签 docker tag nginx:1.20 myrepo/nginx:1.20 # 推送镜像到仓库 docker push myrepo/nginx:1.20 # 容器生命周期 # 创建并启动容器前台 docker run -it --name ubuntu ubuntu:22.04 /bin/bash # 创建并启动容器后台 docker run -d --name nginx -p 80:80 nginx:1.20 # 启动已有容器 docker start nginx # 停止容器 docker stop nginx # 重启容器 docker restart nginx # 强制停止容器 docker kill nginx # 暂停容器 docker pause nginx # 恢复暂停的容器 docker unpause nginx # 删除容器运行中需加-f docker rm nginx # 强制删除运行中的容器 docker rm -f nginx # 删除所有停止的容器 docker container prune # 容器操作 # 查看运行中的容器 docker ps # 查看所有容器含停止 docker ps -a # 查看容器详细信息JSON docker inspect nginx # 查看容器日志实时跟踪 docker logs -f nginx # 进入容器执行命令交互式 docker exec -it nginx /bin/bash # 在容器内执行单条命令 docker exec nginx ls /etc # 从宿主机复制文件到容器 docker cp /path/host.txt nginx:/container/path # 从容器复制文件到宿主机 docker cp nginx:/container/path /path/host.txt # 查看容器内进程 docker top nginx # 查看容器资源占用 docker stats nginx # 查看容器端口映射 docker port nginx # 重命名容器 docker rename old-name new-name # 数据卷 # 创建命名卷 docker volume create my-volume # 列出所有卷 docker volume ls # 查看卷详情 docker volume inspect my-volume # 删除卷 docker volume rm my-volume # 删除未使用的卷 docker volume prune # 挂载命名卷运行容器 docker run -d --name mysql -v my-volume:/var/lib/mysql mysql:8.0 # 挂载宿主机目录bind mount docker run -d --name nginx -v /host/html:/usr/share/nginx/html nginx:1.20 # 网络 # 列出网络 docker network ls # 创建桥接网络 docker network create my-net # 查看网络详情 docker network inspect my-net # 连接容器到网络 docker network connect my-net nginx # 断开容器与网络 docker network disconnect my-net nginx # 删除网络 docker network rm my-net # 删除未使用的网络 docker network prune # 指定网络运行容器 docker run -d --name app --network my-net my-app # Docker Compose # 启动服务后台 docker-compose up -d # 启动服务并重新构建镜像 docker-compose up -d --build # 停止服务 docker-compose stop # 停止并删除容器、网络默认不删卷 docker-compose down # 停止并删除容器、网络、卷危险 docker-compose down -v # 查看服务状态 docker-compose ps # 查看服务日志 docker-compose logs -f app # 重启服务 docker-compose restart # 拉取最新镜像 docker-compose pull # 执行服务中的命令 docker-compose exec app /bin/bash # 清理与系统信息 # 查看Docker版本 docker version # 查看Docker系统信息 docker info # 查看磁盘使用情况 docker system df # 清理所有未使用的资源容器、镜像、网络、卷 docker system prune -a --volumes # 清理未使用的镜像 docker image prune -a # 清理未使用的容器 docker container prune # 清理未使用的网络 docker network prune # 清理未使用的卷 docker volume prune # 查看事件流实时监控 docker events # 查看历史命令 docker history nginx:1.20容器备份恢复将一台机器上的容器备份恢复到另一台机器# 场景A无状态容器如 Spring Boot 镜像→ save/load # 【原机器】1. 提交容器为镜像如果当初是 docker run 起的、没 save 过镜像 docker commit sb-container sb-app:1.0 # 【原机器】2. 导出镜像为 tar docker save -o sb-app.tar sb-app:1.0 # 【原机器】3. 连同 docker-compose.yml 一起拷到新机器 scp sb-app.tar usernew-host:/opt/ scp docker-compose.yml usernew-host:/opt/ # 【新机器】4. 导入镜像 docker load -i /opt/sb-app.tar # 【新机器】5. 启动前提MySQL 等其他依赖已就位 docker-compose up -d # 场景B有状态容器MySQL 数据卷→ alpine tar 法 # 【原机器】1. 停 MySQL 保一致性 docker stop mysql # 【原机器】2. alpine 临时容器把命名卷打成 tar docker run --rm \ -v mysql-data:/volume \ -v /tmp:/backup \ alpine \ tar -czf /backup/mysql-data.tar.gz -C /volume . # 【原机器】3. 拷到新机器 scp /tmp/mysql-data.tar.gz usernew-host:/tmp/ # 【新机器】4. 用同名 compose 先把卷创建出来只起 mysql 让它初始化一次然后停 docker-compose up -d mysql docker-compose stop mysql # 【新机器】5. alpine 临时容器恢复卷数据 docker run --rm \ -v myapp_mysql-data:/volume \ -v /tmp:/backup \ alpine \ sh -c rm -rf /volume/* tar -xzf /backup/mysql-data.tar.gz -C /volume # 【新机器】6. 起全套 docker-compose up -d # 场景CMySQL 跨版本/最稳 → mysqldump SQL 法 # 【原机器】1. dump--single-transaction 保证 InnoDB 一致性 docker exec mysql mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} \ --single-transaction --routines --triggers --all-databases /tmp/backup.sql # 【原机器】2. 拷 SQL 镜像 compose scp /tmp/backup.sql usernew-host:/tmp/ scp sb-app.tar usernew-host:/opt/ # 【新机器】3. load 镜像 起空 MySQL docker load -i /opt/sb-app.tar docker-compose up -d mysql # 此时库是空的 # 【新机器】4. 导入 SQL docker cp /tmp/backup.sql mysql:/tmp/ docker exec -i mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} /tmp/backup.sql # 【新机器】5. 起应用 docker-compose up -d app # 【新机器】6. 验证 docker-compose ps curl http://localhost:8080/actuator/healthDockerFile和docker-compose.yml的用法案例现在有个前后端分离项目app.jar、dist前端代码文件夹、还用到了mysql、redis、nginx;项目拆一下5 样东西 ≠ 1 个 DockerfileDockerfile 一次只构建一个镜像。正确拆法是app.jar → 自己写 Dockerfile 打 Spring Boot 镜像dist nginx → 写一个 Dockerfile把 dist 拷进 nginxmysql / redis → 直接用官方镜像不用自己写 Dockerfilecompose 里配就行一、后端 Dockerfileapp.jar如果用jdk8将FROM eclipse-temurin:21-jre-alpine改为FROM eclipse-temurin:8-jre-alpine# 多阶段构建 # 阶段1构建如果你的 CI 已经 mvn package 了这段可以省直接用阶段2 FROM maven:3.9-eclipse-temurin:21 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -DskipTests # 阶段2运行 FROM eclipse-temurin:21-jre-alpine LABEL maintaineryouexample.com # 时区面试常问为啥容器里时间不对 ENV TZAsia/Shanghai WORKDIR /app # 从构建阶段拷 jarCI 已经打好就用下面这句替代上面阶段1 # COPY target/app.jar /app.jar COPY --frombuild /app/target/*.jar app.jar # JVM 调优8年经验简历能写JVM 参数调优 # -Xms -Xmx 按容器内存来比如容器 1G 就设 512m # UseContainerSupport 让 JVM 识别容器内存上限JDK 8u191 默认开21 肯定开 ENTRYPOINT [java, \ -Xms256m, -Xmx512m, \ -XX:UseG1GC, \ -Duser.timezoneAsia/Shanghai, \ -jar, /app.jar] 如果公司 CI 已经mvn package了阶段1删掉只留阶段2 COPY target/app.jar /app.jar镜像从 700MB 降到 80MB 级alpine jre。二、 前端 Dockerfiledist nginx项目里dist/是 Vuenpm run build出来的跟 nginx 放一起# 多阶段构建 # 阶段1Node 编 dist如果 dist 已经本地打好了这段也可以省 FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci --registryhttps://registry.npmmirror.com COPY . . RUN npm run build # 阶段2Nginx 跑 dist FROM nginx:1.26-alpine # 删掉默认配置 RUN rm /etc/nginx/conf.d/default.conf # 拷自定义 nginx.conf反向代理后端 api 用下面给 COPY nginx.conf /etc/nginx/conf.d/ # 拷 dist本地已有 dist 就 COPY dist /usr/share/nginx/html不用阶段1 COPY --frombuild /app/dist /usr/share/nginx/html EXPOSE 80配套nginx.conf解决前端路由 history 模式 反向代理/api到 Spring Bootserver { listen 80; server_name localhost; # 前端静态资源 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; # Vue Router history 模式必配 } # 反向代理后端接口 location /api/ { proxy_pass http://app:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }注意proxy_pass http://app:8080里的app是 compose service 名靠自定义网络 DNS 解析不是 localhost。三、docker-compose.yml 把 5 样串起来重点交付物version: 3.8 services: # 后端 app: build: context: ./backend # 下放 app.jar Dockerfile dockerfile: Dockerfile container_name: app ports: - 8080:8080 environment: SPRING_PROFILES_ACTIVE: prod SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/appdb?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: root123 SPRING_DATA_REDIS_HOST: redis SPRING_DATA_REDIS_PORT: 6379 volumes: - ./logs:/app/logs # SB 日志挂出来 depends_on: - mysql - redis restart: always networks: - app-net # 前端 nginx nginx: build: context: ./frontend # 下放 dist nginx.conf Dockerfile dockerfile: Dockerfile container_name: nginx ports: - 80:80 depends_on: - app restart: always networks: - app-net # MySQL mysql: image: mysql:8.0 container_name: mysql environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: appdb TZ: Asia/Shanghai ports: - 3306:3306 volumes: - mysql-data:/var/lib/mysql # 首次启动自动执行建表/初始化SQL可选 # - ./init.sql:/docker-entrypoint-initdb.d/init.sql command: --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci --default-authentication-pluginmysql_native_password restart: always networks: - app-net # Redis redis: image: redis:7-alpine container_name: redis ports: - 6379:6379 volumes: - redis-data:/data # 自定义配置可选关保护模式/设密码 # - ./redis.conf:/etc/redis/redis.conf command: redis-server --appendonly yes restart: always networks: - app-net networks: app-net: driver: bridge volumes: mysql-data: redis-data:四、目录结构参考照着摆project/ ├── backend/ │ ├── Dockerfile # 后端的 │ ├── app.jar # mvn package 出来的 │ └── logs/ # 运行时挂出来 ├── frontend/ │ ├── Dockerfile # 前端的 │ ├── dist/ # npm run build 出来的 │ └── nginx.conf ├── docker-compose.yml └── init.sql # (可选) MySQL 初始化五、启动 验证# 构建 启动--build 强制重打镜像改了 Dockerfile 必加 docker-compose up -d --build # 看状态 docker-compose ps # 看后端日志 docker-compose logs -f app # 浏览器 http://服务器IP nginx 80 端口进/api 反向代理到 app:8080多阶段构建压镜像体积Maven 3.9 JDK21 编Alpine JRE21 跑最终镜像 80MB 级镜像分层优化pom.xml 单独 COPY 先dependency:go-offline依赖层缓存nginx 反向代理解决跨域 Vue history 模式try_filescompose 自定义网络 → 服务间用容器名互访不用写 IP有状态服务挂卷mysql-data / redis-datarestart: always⚠️ 一个坑生产别把 mysql/redis 的ports暴露成3306:3306云服务器公网 3306 被扫很正常改成127.0.0.1:3306:3306让 nginx→app→mysql 走内网就行。4. Docker 核心概念4.1 镜像 Image镜像是容器运行的模板里面包含应用程序、依赖库、配置文件、运行命令等。特点镜像是只读的。镜像是分层的。镜像可以基于另一个镜像构建。镜像可以上传到仓库也可以从仓库拉取。示例docker pull nginx:latest docker images4.2 容器 Container容器是镜像运行起来之后的实例。特点一个镜像可以启动多个容器。容器之间默认相互隔离。容器删除后容器可写层中的数据默认会丢失。持久化数据应使用 volume 或 bind mount。示例docker run -d --name my-nginx -p 8080:80 nginx docker ps docker stop my-nginx docker rm my-nginx4.3 仓库 Registry镜像仓库用于保存和分发镜像。常见仓库Docker Hub。阿里云容器镜像服务。腾讯云镜像仓库。Harbor 私有仓库。常用命令docker login docker tag myapp:1.0 username/myapp:1.0 docker push username/myapp:1.0 docker pull username/myapp:1.0AI写代码bash12345. Docker 安装以下以 CentOS Stream 8 为例。5.1 准备环境实验环境容器管理工具Docker Engine。容器运行时containerd、runc。操作系统CentOS Stream 8。5.2 配置 Docker 软件源yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo5.3 安装 Dockeryum install -y docker-ce docker-ce-cli containerd.io5.4 启动 Dockersystemctl enable docker.service --now docker --version systemctl status docker5.5 配置镜像加速mkdir -p /etc/docker vim /etc/docker/daemon.json示例配置{ registry-mirrors: [ https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com ] }重启 Dockersystemctl daemon-reload systemctl restart docker docker info6. Docker 常用命令6.1 镜像命令# 查看本地镜像 docker images # 搜索镜像 docker search nginx # 拉取镜像 docker pull nginx:latest # 删除镜像 docker rmi nginx:latest # 查看镜像详细信息 docker inspect nginx # 查看镜像构建历史 docker history nginx6.2 容器命令# 创建并启动容器 docker run -d --name web -p 8080:80 nginx # 查看正在运行的容器 docker ps # 查看所有容器 docker ps -a # 停止容器 docker stop web # 启动已停止容器 docker start web # 重启容器 docker restart web # 删除容器 docker rm web # 强制删除运行中的容器 docker rm -f web6.3 进入容器docker exec -it web bash如果容器中没有 bash可以使用 shdocker exec -it web sh6.4 查看日志docker logs web docker logs -f web docker logs --tail 100 web6.5 文件复制# 从宿主机复制文件到容器 docker cp ./index.html web:/usr/share/nginx/html/index.html # 从容器复制文件到宿主机 docker cp web:/etc/nginx/nginx.conf ./nginx.conf6.6 查看资源占用docker stats6.7 清理资源# 删除停止的容器 docker container prune # 删除无用镜像 docker image prune # 删除无用网络 docker network prune # 删除无用 volume docker volume prune # 清理所有无用资源 docker system prune注意docker system prune -a会删除所有未被容器使用的镜像生产环境慎用。7. docker run 常用参数docker run [OPTIONS] IMAGE [COMMAND]常用参数参数作用-d后台运行-it交互式终端--name指定容器名称-p端口映射-v挂载目录或数据卷-e设置环境变量--network指定网络--restart设置重启策略--rm容器退出后自动删除--privileged开启特权模式--memory限制内存--cpus限制 CPU示例docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -v mysql-data:/var/lib/mysql \ --restartalways \ mysql:8.08. Docker 网络8.1 网络模式Docker 常见网络模式网络模式说明bridge默认模式容器通过 docker0 网桥通信host容器直接使用宿主机网络none容器没有网络container与另一个容器共享网络命名空间自定义 bridge推荐用于多个容器互相通信8.2 常用网络命令# 查看网络 docker network ls # 查看网络详情 docker network inspect bridge # 创建自定义网络 docker network create app-net # 使用指定网络启动容器 docker run -d --name nginx --network app-net nginx # 将容器连接到网络 docker network connect app-net nginx # 将容器移出网络 docker network disconnect app-net nginx8.3 容器之间通信推荐使用自定义网络。处于同一个自定义网络中的容器可以通过容器名互相访问。示例docker network create app-net docker run -d --name redis --network app-net redis:7 docker run -it --rm --network app-net redis:7 redis-cli -h redis9. Docker 存储9.1 容器数据为什么会丢失容器运行后会在镜像只读层上增加一层可写层。如果删除容器这一层也会被删除。因此数据库、上传文件、日志等需要持久化的数据不能只放在容器内部。9.2 volume 数据卷volume 是 Docker 管理的数据卷适合保存数据库数据。# 创建数据卷 docker volume create mysql-data # 查看数据卷 docker volume ls # 查看数据卷详情 docker volume inspect mysql-data # 使用数据卷 docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD123456 \ -v mysql-data:/var/lib/mysql \ mysql:8.09.3 bind mount 目录挂载bind mount 是把宿主机目录挂载到容器中适合挂载配置文件、项目代码。docker run -d \ --name web \ -p 8080:80 \ -v /opt/nginx/html:/usr/share/nginx/html \ nginx9.4 volume 与 bind mount 对比对比项volumebind mount管理方Docker 管理用户自己管理路径Docker 默认路径用户指定路径适用场景数据库、持久化数据配置文件、代码目录可移植性较好依赖宿主机目录结构10. DockerfileDockerfile 是用来构建镜像的文本文件里面定义了基础镜像、依赖安装、文件复制、启动命令等步骤。10.1 常用指令指令作用FROM指定基础镜像LABEL添加镜像元数据WORKDIR指定工作目录COPY复制文件到镜像ADD复制文件支持自动解压和 URLRUN构建镜像时执行命令CMD容器启动时默认命令ENTRYPOINT容器启动入口ENV设置环境变量ARG构建参数EXPOSE声明容器端口VOLUME声明挂载点USER指定运行用户10.2 Dockerfile 示例Nginx 静态站点FROM nginx:1.25-alpine COPY ./dist /usr/share/nginx/html EXPOSE 80 CMD [nginx, -g, daemon off;]构建和运行docker build -t my-nginx-site:1.0 . docker run -d --name site -p 8080:80 my-nginx-site:1.010.3 Dockerfile 示例Java 应用FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY target/app.jar /app/app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app/app.jar]10.4 CMD 与 ENTRYPOINT 区别CMD提供默认启动命令容易被docker run后面的命令覆盖。ENTRYPOINT定义容器固定入口更适合作为主程序入口。示例ENTRYPOINT [java, -jar, /app/app.jar] CMD [--spring.profiles.activeprod]运行时可以覆盖CMD参数docker run myapp:1.0 --spring.profiles.activetest10.5 镜像构建优化选择更小的基础镜像例如 alpine、slim。合并相关RUN指令减少镜像层数。使用.dockerignore排除无关文件。利用构建缓存把不常变化的步骤放前面。使用多阶段构建减少最终镜像体积。不把密码、密钥写入镜像。尽量使用非 root 用户运行应用。10.6 多阶段构建示例FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /build COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --frombuilder /build/target/app.jar /app/app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app/app.jar]11. Docker ComposeDocker Compose 用于定义和运行多个容器。适合本地开发、测试环境和小规模部署。11.1 Compose 常用命令# 启动服务 docker compose up -d # 查看服务 docker compose ps # 查看日志 docker compose logs -f # 停止并删除服务 docker compose down # 重新构建镜像并启动 docker compose up -d --build # 停止服务但不删除容器 docker compose stop # 启动已停止服务 docker compose start11.2 Compose 示例Web MySQL Redisservices: app: build: . container_name: demo-app ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/demo?useSSLfalseserverTimezoneAsia/Shanghai SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: 123456 SPRING_REDIS_HOST: redis depends_on: - mysql - redis networks: - app-net mysql: image: mysql:8.0 container_name: demo-mysql ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: demo volumes: - mysql-data:/var/lib/mysql networks: - app-net redis: image: redis:7 container_name: demo-redis ports: - 6379:6379 networks: - app-net networks: app-net: volumes: mysql-data:启动docker compose up -d12. Docker 日志与排错12.1 常见排错命令# 查看容器状态 docker ps -a # 查看容器日志 docker logs 容器名 # 查看容器详细信息 docker inspect 容器名 # 进入容器检查 docker exec -it 容器名 sh # 查看容器资源占用 docker stats # 查看端口映射 docker port 容器名 # 查看 Docker 服务日志 journalctl -u docker -f12.2 容器启动失败排查思路用docker ps -a查看容器是否退出。用docker logs查看应用错误日志。检查端口是否被占用。检查环境变量是否配置正确。检查挂载路径是否存在、权限是否正确。检查镜像架构是否与服务器架构匹配。检查容器启动命令是否正确。12.3 端口访问不了排查思路容器是否正在运行。是否配置了-p 宿主机端口:容器端口。应用是否监听0.0.0.0而不是只监听127.0.0.1。宿主机防火墙或安全组是否放行。容器内部服务是否正常。13. Docker 安全建议不在镜像中写入密码、Token、私钥。尽量不要使用--privileged。生产环境尽量使用固定版本标签不使用latest。使用非 root 用户运行应用。只暴露必要端口。定期更新基础镜像。对镜像进行漏洞扫描。限制容器 CPU 和内存资源。对重要数据使用 volume 持久化并定期备份。14. Docker 实践项目项目 1使用 Docker 部署 Nginx 静态网站目标使用 Nginx 容器运行一个静态页面。将宿主机目录挂载到容器。通过浏览器访问页面。步骤mkdir -p /opt/docker-demo/html echo Hello Docker /opt/docker-demo/html/index.html docker run -d \ --name nginx-demo \ -p 8080:80 \ -v /opt/docker-demo/html:/usr/share/nginx/html \ nginx:1.25访问http://服务器IP:8080项目 2使用 Docker 部署 MySQL目标启动 MySQL 8 容器。使用 volume 持久化数据。使用客户端连接数据库。步骤docker volume create mysql-data docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD123456 \ -e MYSQL_DATABASEdemo \ -v mysql-data:/var/lib/mysql \ --restartalways \ mysql:8.0进入 MySQLdocker exec -it mysql8 mysql -uroot -p123456项目 3使用 Dockerfile 打包 Spring Boot 项目目标将 Spring Boot 项目打包成 jar。编写 Dockerfile。构建镜像并运行容器。DockerfileFROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]构建运行mvn clean package -DskipTests docker build -t springboot-demo:1.0 . docker run -d \ --name springboot-demo \ -p 8080:8080 \ springboot-demo:1.0项目 4使用 Docker Compose 部署完整后端环境目标使用 Compose 同时启动应用、MySQL、Redis。应用通过服务名访问 MySQL 和 Redis。使用 volume 保存 MySQL 数据。文件docker-compose.ymlservices: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: demo volumes: - mysql-data:/var/lib/mysql networks: - app-net redis: image: redis:7 networks: - app-net app: build: . ports: - 8080:8080 environment: MYSQL_HOST: mysql REDIS_HOST: redis depends_on: - mysql - redis networks: - app-net networks: app-net: volumes: mysql-data:启动docker compose up -d --build停止docker compose down15. Docker 常见面试题1. Docker 和虚拟机有什么区别Docker 是进程级隔离共享宿主机内核启动快、资源占用少虚拟机是硬件级虚拟化每台虚拟机都有完整操作系统隔离性更强但资源占用更大。2. Docker 镜像和容器有什么区别镜像是只读模板容器是镜像运行后的实例。一个镜像可以创建多个容器容器有自己的可写层。3. Docker 为什么启动快容器不需要启动完整操作系统而是共享宿主机内核本质上是启动一个隔离的进程所以启动速度很快。4. Docker 底层隔离原理是什么主要依赖 Linux Namespace 和 Cgroups。Namespace 负责隔离进程、网络、文件系统等资源Cgroups 负责限制和统计 CPU、内存、I/O 等资源。5. Docker 镜像为什么是分层的镜像分层可以复用已有层减少存储空间和网络传输成本。构建镜像时如果某一层没有变化可以直接使用 缓存 。6. Dockerfile 中 CMD 和 ENTRYPOINT 有什么区别CMD是默认命令容易被docker run后面的参数覆盖ENTRYPOINT是容器启动入口通常用于固定启动主程序。二者可以配合使用ENTRYPOINT定义程序CMD提供默认参数。7. COPY 和 ADD 有什么区别COPY只负责复制文件或目录语义更清晰推荐优先使用。ADD除了复制还支持自动解压 tar 文件和从 URL 添加文件。8. volume 和 bind mount 有什么区别volume 由 Docker 管理适合数据库等持久化数据bind mount 使用宿主机指定路径适合挂载配置文件或代码目录。9. 容器之间如何通信推荐创建自定义 bridge 网络然后让容器加入同一个网络。这样容器之间可以通过容器名或服务名访问。10. Docker Compose 是什么Docker Compose 是用于定义和管理多容器应用的工具通过docker-compose.yml描述服务、网络、数据卷等配置再用一条命令启动整个应用。11. 如何减少 Docker 镜像体积可以选择更小的基础镜像使用多阶段构建合并RUN指令清理安装缓存使用.dockerignore排除无关文件并避免把源码、测试文件、构建工具放入最终镜像。12. 容器退出后数据会不会丢失如果数据只保存在容器可写层删除容器后会丢失。需要持久化的数据应保存到 volume 或 bind mount 中。13. 如何查看容器日志docker logs 容器名 docker logs -f 容器名 docker logs --tail 100 容器名14. 如何进入正在运行的容器docker exec -it 容器名 bash如果没有 bashdocker exec -it 容器名 sh15. Docker 容器访问不了外部端口怎么办排查方向容器是否运行。是否正确配置-p端口映射。应用是否监听0.0.0.0。防火墙或云服务器安全组是否放行。容器日志是否报错。16. Docker 中latest标签有什么问题latest不代表最新稳定版本只是一个普通标签。生产环境使用latest可能导致版本不可控建议使用明确版本号。17. 什么是 Dockerfile 构建缓存Docker 构建镜像时会按指令逐层执行。如果某一层指令和上下文没有变化Docker 会复用之前的缓存从而加快构建速度。18. 如何限制容器资源docker run -d \ --name app \ --memory512m \ --cpus1 \ nginx19. 容器内应用为什么要前台运行容器的生命周期由主进程决定。如果主进程退出容器也会退出。因此容器中的主应用一般要以前台方式运行。20. Docker 适合运行有状态服务吗可以运行但要正确处理数据持久化、备份、恢复、网络和资源限制。数据库这类有状态服务在生产环境中要更加谨慎通常需要结合专业运维方案。16. 学习路线建议先掌握镜像、容器、仓库三个核心概念。熟练使用docker run、docker ps、docker logs、docker exec。学会网络和数据卷理解容器间通信和数据持久化。学会编写 Dockerfile把自己的应用打包成镜像。学会 Docker Compose能启动一套完整开发环境。最后再学习 Kubernetes、CI/CD、镜像仓库和生产环境部署。