文章目录
操作题
题目需求:
请编写一个 Dockerfile,满足以下条件:
- 基础镜像使用官方的
python:3.9-slim(轻量版 Python 3.9 镜像)。 - 镜像的元数据中添加作者信息,键为
maintainer,值为yourname@example.com(请用实际名称或占位符)。 - 设置环境变量
APP_HOME,值为/app,后续操作以该目录为工作目录。 - 将宿主机当前目录下的
requirements.txt(依赖清单)和app.py(应用代码)复制到容器的工作目录中。 - 执行命令安装
requirements.txt中的依赖(命令为pip install --no-cache-dir -r requirements.txt)。 - 声明容器运行时会监听 5000 端口(TCP 协议)。
- 定义容器启动时的默认命令,运行
app.py(命令为python app.py)。 - 为容器内的
/app/logs目录创建匿名卷(用于持久化日志)。
FROM python:3.9-slim
LABEL maintainer="yourname@example.com"
ENV APP_HOME="/app"
WORKDIR $APP_HOME # 工作目录为 /app
COPY ./requirements.txt .
COPY ./app.py .
RUN mkdir logs # 在工作目录下创建 logs 目录(即 /app/logs)
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
VOLUME ["./logs"] # 等价于 /app/logs(因 WORKDIR 为 /app)
CMD ["python", "app.py"]
题目需求:
请编写一个 docker-compose.yml 文件,实现一个包含 Web 服务 和 MySQL 数据库 的简单应用,具体要求如下:
-
Web 服务(service 名称:
web)- 基于当前目录下
./webapp文件夹中的Dockerfile构建镜像(该 Dockerfile 无需编写,只需配置构建路径)。 - 容器内 Web 应用监听 8080 端口,需将宿主机的 80 端口映射到容器的 8080 端口。
- 依赖
mysql服务(确保mysql启动后再启动web)。 - 需设置环境变量
DB_HOST为mysql(指向数据库服务),ENV为production。 - 加入自定义网络
app-net。
- 基于当前目录下
-
MySQL 服务(service 名称:
mysql)- 使用官方
mysql:8.0镜像。 - 暴露容器内 3306 端口(仅允许内部服务访问,不映射到宿主机)。
- 设置环境变量
MYSQL_ROOT_PASSWORD为root123,MYSQL_DATABASE为mydb(从.env文件加载,而非直接写在 yml 中)。 - 需将数据持久化到宿主机的
./mysql-data目录(挂载到容器内/var/lib/mysql路径)。 - 加入自定义网络
app-net。
- 使用官方
-
其他要求
- 定义自定义网络
app-net(驱动为bridge)。 - Compose 配置版本使用
3.8。
- 定义自定义网络
version: '3.8' # 指定 Compose 版本
# 定义自定义网络
networks:
app-net:
driver: bridge # 使用桥接模式驱动
services:
# Web 服务配置
web:
build: ./webapp # 基于 ./webapp 目录下的 Dockerfile 构建镜像
ports:
- "80:8080" # 宿主机 80 端口映射到容器 8080 端口
depends_on:
- mysql # 依赖 mysql 服务,确保其先启动
environment:
- DB_HOST=mysql # 环境变量:数据库主机指向 mysql 服务
- ENV=production # 环境变量:运行环境为生产环境
networks:
- app-net # 加入自定义网络 app-net
# MySQL 服务配置
mysql:
image: mysql:8.0 # 使用官方 MySQL 8.0 镜像
expose:
- "3306" # 暴露 3306 端口(仅内部服务可访问)
env_file:
- .env # 从 .env 文件加载环境变量(避免明文写密码)
volumes:
- ./mysql-data:/var/lib/mysql # 宿主机 ./mysql-data 目录挂载到容器数据目录(持久化数据)
networks:
- app-net # 加入自定义网络 app-net
Java、Spring环境读取docker环境变量
在 Java 程序(尤其是 Spring 应用)中读取 Docker Compose 定义的环境变量,有明确的方法和优先级规则。以下分场景说明:
一、纯 Java 程序如何读取环境变量
纯 Java 程序(非 Spring)可通过 System.getenv() 方法直接读取环境变量,用法如下:
假设 docker-compose.yml 中定义:
services:
app:
environment:
- DB_HOST=mysql
- APP_PORT=8080
Java 代码中读取:
public class Main {
public static void main(String[] args) {
// 读取环境变量
String dbHost = System.getenv("DB_HOST"); // 结果为 "mysql"
String appPort = System.getenv("APP_PORT"); // 结果为 "8080"
System.out.println("数据库地址:" + dbHost);
System.out.println("应用端口:" + appPort);
}
}
二、Spring 的 yml 配置文件如何读取环境变量
Spring 框架支持在配置文件(如 application.yml 或 application.properties)中通过 ${变量名} 引用环境变量,实现配置动态注入。
步骤示例:
-
Docker Compose 定义环境变量:
services: spring-app: environment: - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb - LOG_LEVEL=INFO -
Spring 的
application.yml引用:# 直接引用环境变量 spring: datasource: url: ${SPRING_DATASOURCE_URL} # 引用环境变量,值为 "jdbc:mysql://mysql:3306/mydb" username: root password: ${DB_PASSWORD:defaultpass} # 带默认值:若环境变量不存在,使用 "defaultpass" # 引用后赋值给其他配置 logging: level: root: ${LOG_LEVEL} # 引用环境变量,值为 "INFO" -
在 Spring 组件中使用:
通过@Value注解或@ConfigurationProperties读取配置(底层已关联环境变量):@RestController public class MyController { // 直接读取环境变量(不推荐,建议通过配置文件中转) @Value("${DB_HOST:mysql}") private String dbHost; // 读取配置文件中引用环境变量的值 @Value("${spring.datasource.url}") private String jdbcUrl; @GetMapping("/config") public String getConfig() { return "DB地址:" + dbHost + ",JDBC地址:" + jdbcUrl; } }
三、配置冲突时的优先级(Spring yml vs Docker Compose 环境变量)
当 Spring 的 yml 配置文件中直接写死值,且 Docker Compose 中定义了同名环境变量 时,Docker Compose 的环境变量会覆盖 Spring 配置文件中的值。
示例说明:
-
Spring 的
application.yml中设置:app: name: my-spring-app # 写死的值 -
Docker Compose 中定义同名环境变量:
services: spring-app: environment: - app.name=docker-override # 同名环境变量 -
实际生效的值:
Spring 会优先使用环境变量app.name=docker-override,而非配置文件中的my-spring-app。
四、Spring 配置的优先级规则
Spring 读取配置的优先级(从高到低)为:
- 命令行参数(如
java -jar app.jar --app.name=xxx) - 容器环境变量(Docker Compose 中
environment定义的变量) - 系统环境变量
application-{profile}.yml(激活的环境配置文件)application.yml(默认配置文件)- 配置类中通过
@Value定义的默认值
因此,Docker Compose 定义的环境变量(属于第 2 级)会覆盖配置文件中的值(第 4、5 级),这也是容器化部署中动态配置的核心机制(无需修改代码,通过环境变量即可调整配置)。
总结
- 纯 Java:用
System.getenv("变量名")读取。 - Spring yml:用
${变量名}引用,支持默认值(${变量名:默认值})。 - 优先级:Docker Compose 环境变量 > Spring 配置文件中的值,符合容器化动态配置的需求。
Dockerfile与docker-compose.yml操作及环境变量读取
1799

被折叠的 条评论
为什么被折叠?



