在我的Spring Boot应用中,我想将属性外部化以在Docker容器中运行。首次部署时,应用程序当前当前属于my-server/src/main/resources/application.yml
中的属性会按预期加载和使用。一切都很好。
但是,我的问题是我需要根据需要更新这些属性,因此我需要在Docker容器上访问application.yml
文件。但是在这一点上,它在运行buildDocker
任务之前尚未包含在build/docker/
目录中,因此在第一次部署后无法复制或可访问。
因此,我尝试的是将yaml文件复制到docker/
构建目录中,将其复制到可访问目录(/opt/meanwhileinhell/myapp/conf
),然后使用spring.config.location
属性将配置的位置传递给我的Dockerfile中的JAR:
ENTRYPOINT ["java",
...
"-jar", "/app.jar",
"--spring.config.location=classpath:${configDirectory}"]
查看在Docker容器上运行的命令,我可以看到这是预期的:
/app.jar --spring.config.location=classpath:/opt/meanwhileinhell/myapp/conf]
但是,当我更新此文件中的属性并重新启动Docker容器时,它不会拾取更改。文件权限为:
-rw-r--r-- 1 root root 618 Sep 5 13:59 application.yml
文档指出:
配置自定义配置位置时,它们还会加上它们 到默认位置。自定义位置在 默认位置。
我似乎无法弄清楚我在做什么错或误解,但更重要的是,这是将这种类型的Docker方案外部化的正确方法?
docker Image Configuration
如果您寻找Spring推荐启动Spring Boot驱动的Docker容器的方式,那就是您发现的:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
这意味着您的图像扩展了OpenJDK,并且您的容器具有自己的环境。如果您这样做,则足以将您要覆盖的内容声明为环境属性,而Spring Boot将获取它们,因为环境变量优先于YML文件。
环境变量也可以在docker命令中传递,以启动使用所需配置的容器。如果要设置JVM内存的限制,请参见下面的链接。
docker构成样本
在这里,您有一个示例,说明了我如何使用Docker Compose启动简单的应用程序环境。如您所见,我在此处声明spring.datasource.url
属性为环境变量,因此它覆盖了您在application.yml
文件中所拥有的任何内容。
version: '2'
services:
myapp:
image: mycompany/myapp:1.0.0
container_name: myapp
depends_on:
- mysql
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp?useUnicode=true&characterEncoding=utf8&useSSL=false
ports:
- 8080:8080
mysql:
image: mysql:5.7.19
container_name: mysql
volumes:
- /home/docker/volumes/myapp/mysql/:/var/lib/mysql/
environment:
- MYSQL_USER=root
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE=myapp
command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8
另请参阅:
- 如何将环境变量传递给Docker容器?
- 限制Docker容器中的JVM内存消耗
我个人会考虑两个选项:
-
使用每个配置的环境变量
app: image: my-app:latest ports: - "8080:8080" environment: SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/table
-
使用
SPRING_APPLICATION_JSON
app: image: my-app:latest ports: - "8080:8080" environment: SPRING_APPLICATION_JSON: '{ "spring.datasource.url": "jdbc:mysql://db:3306/table", }'
我个人会使用Spring Cloud Config Server,而不是尝试在整个地方设置属性文件。
tl; dr允许您在集中位置中以每个环境/配置文件级别的git(允许版本控制,分支等)保持属性,然后通过静止来提供。Spring Boot对此有全力支持;实际上,这只是另一个最终在您的环境中的属性来源。
https://spring.io/guides/gs/centralized-configuration/
,所以我设法使它正常工作。而不是将class路径传递给我的dockerfile中的目录:
"--spring.config.location=classpath:${configDirectory}"]
我尝试传递文件的完整位置:
"--spring.config.location=file:${configDirectory}/application.yml"]
现在,此docker容器的重新启动。
xtreme骑自行车的答案的变体,这次是将弹簧靴战争部署到dockerized tomcat ………
我建议您在您的应用中包含名义application.yml
,但请使用Docker环境变量覆盖任何需要特定环境变化的单个键。
我推荐这种方法的原因(使用Docker环境变量)是:
- 您的Docker映像可以使用恰好与您可能用于本地开发相同的人工制品
- 使用音量安装很痛苦;您需要在某个地方找到他们在码头主持人上生活的地方 - 这将那个主机变成雪花
- 使用Docker Secrets很痛苦;图像或应用程序层需要更改以从文件系统明确查找秘密
Spring Boot的外部配置文档解释了通过命令行提供环境的两种方法:
- un*x env vars(即
SPRING_DATASOURCE_USERNAME=helloworld
) - Java选项(即
-Dspring.datasource.username=helloworld
)
我更喜欢Java选项,因为它们表达了一个明确的意图:"这是针对以下Java过程的,并且仅针对该Java过程。
最后:我将使用Tomcat的CATALINA_OPTS
作为传递这些Java选项的机制。catalina.sh
的文档:
(可选)Java运行时选项在"开始"时使用 执行"运行"或"调试"命令。 在此处包含所有选项,而不是在Java_opts中 仅由Tomcat本身使用,而不是由停止过程使用 版本命令等 示例是堆尺寸,GC记录,JMX端口等。
因为CATALINA_OPTS
比使您的Docker映像负责创建setenv.sh
并将适当的Docker env声明传递到其中更容易。
构建您的 .war
伪像这样:
./gradlew war
我们期望gradle输出.war
CC_19。
使用这样的dockerfile:
FROM tomcat:8.5.16-jre8-alpine
EXPOSE 8080
COPY build/libs/api-0.0.1-SNAPSHOT.war /usr/local/tomcat/webapps/v1.war
CMD ["catalina.sh", "run"]
构建您的Docker映像这样:
docker build . --tag=my-api
将CATALINA_OPTS
传递到您的容器中:
docker run -it
-p 8080:8080
-e CATALINA_OPTS="
-Dspring.datasource.url='jdbc:mysql://mydatabase.stackoverflow.com:3306'
-Dspring.datasource.username=myuser
"
my-api
和docker-compose变体看起来像:
version: '3.2'
services:
web:
image: my-api
ports:
- "8080:8080"
environment:
- >
CATALINA_OPTS=
-Dspring.datasource.url='jdbc:mysql://mydatabase.stackoverflow.com:3306'
-Dspring.datasource.username=myuser
您的方法绝对是一个可行的解决方案,但是不建议这样做,因为它使您的图像无法在不同的生产和开发环境之间移动。容器应该是不可变的,所有环境配置都应被外部化。
对于Spring Boot,有非常强大的项目,可让您外部化配置。它称为Spring Cloud Config。配置服务器允许您将特定于环境的配置保存在GIT存储库中,并将配置提供给需要它的应用程序。您基本上只是保存相同的应用程序。
遵循此方法,您可以为不同环境定义多个配置文件,并使您的Docker容器不变。
将spring.config.additional-location
设置为entrypoint(以/结束)在 dockerfile 上,将卷安装到 application.yml
的主机文件夹
dockerfile
RUN mkdir /opt/meanwhileinhell/myapp/conf
(...)
ENTRYPOINT ["java", "-Dspring.config.additional-location=/opt/meanwhileinhell/myapp/conf/", "-jar", "/opt/meanwhileinhell/myapp/app.jar"]
当我们要指定目录位置时默认值。https://springframework.guru/spring-external-configuration-data/
更改重新启动需要application.yml
将位于主机机上,并用音量引用
docker-compose.yml
...
volumes:
- my-server/src/main/resources:/opt/meanwhileinhell/myapp/conf
...
其他替代方法是 docker-compose.yml 上的环境:...环境:-spring.config.Additional-Location =/opt/opt/opt/myapp/conf/conf/conf/conf/conf/conf/conf/卷: - My-Server/src/main/resources:/opt/opt/yywhileinhell/myapp/conf...
Spring<2.x 使用spring.config.location
代替spring.config.additional-location