Dockerfile、docker-compose.yml练习

Dockerfile与docker-compose.yml操作及环境变量读取

操作题

题目需求:
请编写一个 Dockerfile,满足以下条件:

  1. 基础镜像使用官方的 python:3.9-slim(轻量版 Python 3.9 镜像)。
  2. 镜像的元数据中添加作者信息,键为 maintainer,值为 yourname@example.com(请用实际名称或占位符)。
  3. 设置环境变量 APP_HOME,值为 /app,后续操作以该目录为工作目录。
  4. 将宿主机当前目录下的 requirements.txt(依赖清单)和 app.py(应用代码)复制到容器的工作目录中。
  5. 执行命令安装 requirements.txt 中的依赖(命令为 pip install --no-cache-dir -r requirements.txt)。
  6. 声明容器运行时会监听 5000 端口(TCP 协议)。
  7. 定义容器启动时的默认命令,运行 app.py(命令为 python app.py)。
  8. 为容器内的 /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 数据库 的简单应用,具体要求如下:

  1. Web 服务(service 名称:web

    • 基于当前目录下 ./webapp 文件夹中的 Dockerfile 构建镜像(该 Dockerfile 无需编写,只需配置构建路径)。
    • 容器内 Web 应用监听 8080 端口,需将宿主机的 80 端口映射到容器的 8080 端口。
    • 依赖 mysql 服务(确保 mysql 启动后再启动 web)。
    • 需设置环境变量 DB_HOSTmysql(指向数据库服务),ENVproduction
    • 加入自定义网络 app-net
  2. MySQL 服务(service 名称:mysql

    • 使用官方 mysql:8.0 镜像。
    • 暴露容器内 3306 端口(仅允许内部服务访问,不映射到宿主机)。
    • 设置环境变量 MYSQL_ROOT_PASSWORDroot123MYSQL_DATABASEmydb(从 .env 文件加载,而非直接写在 yml 中)。
    • 需将数据持久化到宿主机的 ./mysql-data 目录(挂载到容器内 /var/lib/mysql 路径)。
    • 加入自定义网络 app-net
  3. 其他要求

    • 定义自定义网络 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.ymlapplication.properties)中通过 ${变量名} 引用环境变量,实现配置动态注入。

步骤示例:
  1. Docker Compose 定义环境变量

    services:
      spring-app:
        environment:
          - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb
          - LOG_LEVEL=INFO
    
  2. 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"
    
  3. 在 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 配置文件中的值

示例说明:
  1. Spring 的 application.yml 中设置

    app:
      name: my-spring-app  # 写死的值
    
  2. Docker Compose 中定义同名环境变量

    services:
      spring-app:
        environment:
          - app.name=docker-override  # 同名环境变量
    
  3. 实际生效的值
    Spring 会优先使用环境变量 app.name=docker-override,而非配置文件中的 my-spring-app

四、Spring 配置的优先级规则

Spring 读取配置的优先级(从高到低)为:

  1. 命令行参数(如 java -jar app.jar --app.name=xxx
  2. 容器环境变量(Docker Compose 中 environment 定义的变量)
  3. 系统环境变量
  4. application-{profile}.yml(激活的环境配置文件)
  5. application.yml(默认配置文件)
  6. 配置类中通过 @Value 定义的默认值

因此,Docker Compose 定义的环境变量(属于第 2 级)会覆盖配置文件中的值(第 4、5 级),这也是容器化部署中动态配置的核心机制(无需修改代码,通过环境变量即可调整配置)。

总结

  • 纯 Java:用 System.getenv("变量名") 读取。
  • Spring yml:用 ${变量名} 引用,支持默认值(${变量名:默认值})。
  • 优先级:Docker Compose 环境变量 > Spring 配置文件中的值,符合容器化动态配置的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值