Play Framework生产环境未加载prod.conf仍用H2数据库问题排查
First off, let's address your PostgreSQL URL question first: Yes, your URL jdbc:postgresql://db:5432/db is correct assuming your PostgreSQL container is named db and both containers are on the same Docker network. Docker's internal DNS resolves container names to their IPs within the network, so this should work as long as the PostgreSQL container is running and accessible.
Now onto the main problem: your app is still using the H2 config from application.conf instead of prod.conf. Let's break down the fixes:
1. Fix the Dockerfile ENTRYPOINT Argument Format
The critical mistake here is how you're passing JVM system properties in your ENTRYPOINT. When using the exec form (array syntax), each command-line argument needs to be a separate element in the array. Right now, you're bundling two -D flags into a single string:
# ❌ Wrong: Treats both flags as a single JVM argument ENTRYPOINT ["target/universal/stage/bin/newsapi", "-Dplay.http.secret.key=KEY -Dconfig.resource=prod.conf"]
JVM will interpret this entire string as a single system property (with a key of play.http.secret.key and value of KEY -Dconfig.resource=prod.conf), completely ignoring the config.resource flag. Fix this by splitting the arguments:
# ✅ Correct: Each JVM flag is a separate array element ENTRYPOINT ["target/universal/stage/bin/newsapi", "-Dplay.http.secret.key=KEY", "-Dconfig.resource=prod.conf"]
For better clarity, you can also set a working directory to avoid long paths:
WORKDIR /target/universal/stage ENTRYPOINT ["./bin/newsapi", "-Dplay.http.secret.key=KEY", "-Dconfig.resource=prod.conf"]
2. Verify prod.conf Placement & Configuration
- Ensure
prod.conflives in your project'sconf/directory. When you runsbt stage, this file will be copied totarget/universal/stage/conf/and added to the app's classpath, so-Dconfig.resource=prod.confcan find it. - Double-check your
prod.conffor redundant or misaligned settings. Your current config has duplicateprofile/driverentries (you only need one), andmaxConnectionsshould be nested under thedbblock for Slick:slick.dbs.default { profile = "slick.jdbc.PostgresProfile$" db { dataSourceClass = "slick.jdbc.DatabaseUrlDataSource" numThreads = 8 driver = "org.postgresql.Driver" url = "jdbc:postgresql://db:5432/db" user = "user" password = "password" maxConnections = 8 # Move this inside the db block } }
3. Verify Configuration Loading (Optional)
To confirm your app is picking up prod.conf, add a quick log statement on startup to print the active database URL. For example, in a Play controller or startup hook:
import play.api.Configuration class StartupHook(config: Configuration) { val dbUrl = config.get[String]("slick.dbs.default.db.url") println(s"Active database URL: $dbUrl") }
This will let you see exactly which URL the app is using when it starts.
Final Checks
- Rebuild your Docker image after making these changes (old images won't pick up the Dockerfile fixes).
- Ensure your PostgreSQL container is running and listening on port 5432 within the Docker network.
内容的提问来源于stack exchange,提问作者Linde_98

