Connecting Next.js with server actions to database with Internal Connection URL
To Reproduce
After I created the Next application and deployed it to Dokploy and connected to the Dokploy database (PostgreSQL), communication works if I connect via an external connection string, but when I change that connection string to internal in the environment, then the build of Next application crashes.
Current vs. Expected behavior
I expect to have a connection to the database through internal communication on the server and not through the Internet. I see internet connect to databse as a huge security flaw.
Provide environment information
Ubuntu, Hetzner cax11 4gb.
Error in dokploy after I made change in ENV from external to internal connection string...
Initializing deployment
Build heroku_buildpacks: ✅
Source Type: github: ✅
24: Pulling from heroku/builder
Digest: sha256:11c05fd10f421614227b72ad21c5e0d44ca3ca1a3e1f6592da92f039e09d33f9
Status: Image is up to date for heroku/builder:24
24: Pulling from heroku/heroku
Digest: sha256:b2e3a768f6a89d3c47def9bda468b15eb9ba66ca4973e05546417b99bdefe94a
Status: Image is up to date for heroku/heroku:24
===> ANALYZING
Restoring data for SBOM from previous image
===> DETECTING
2 of 5 buildpacks participating
heroku/nodejs-engine 3.2.14
heroku/nodejs-npm-install 3.2.14
===> RESTORING
Restoring metadata for "heroku/nodejs-engine:web_env" from app image
Restoring metadata for "heroku/nodejs-engine:dist" from app image
Restoring metadata for "heroku/nodejs-engine:node_runtime_metrics" from app image
Restoring metadata for "heroku/nodejs-npm-install:npm_runtime_config" from app image
Restoring metadata for "heroku/nodejs-npm-install:npm_cache" from cache
Restoring data for "heroku/nodejs-engine:dist" from cache
Restoring data for "heroku/nodejs-npm-install:npm_cache" from cache
===> BUILDING
[Heroku Node.js Engine Buildpack]
[Checking Node.js version]
Node.js version not specified, using 20.x
Resolved Node.js version: 20.17.0
[Installing Node.js distribution]
Reusing Node.js 20.17.0 (linux-arm64)
Installing application metrics scripts
# Heroku Node.js npm Install Buildpack
- Installing node modules
- Using npm version `10.8.2`
- Restoring npm cache
- Configuring npm cache directory
- Running `npm ci "--production=false"`
npm warn config production Use `--omit=dev` instead.
added 52 packages, and audited 53 packages in 6s
3 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
- Done (6.321s)
- Running scripts
- Running `npm run build`
> [email protected] build
> next build
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
▲ Next.js 14.2.13
Creating an optimized production build ...
✓ Compiled successfully
Linting and checking validity of types ...
Collecting page data ...
Generating static pages (0/4) ...
Generating static pages (1/4)
Generating static pages (2/4)
Generating static pages (3/4)
Error: getaddrinfo EAI_AGAIN testing-test-2b746e
at /workspace/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async e (/workspace/.next/server/app/page.js:1:2507)
at async a (/workspace/.next/server/app/page.js:1:2581) {
errno: -3001,
code: 'EAI_AGAIN',
syscall: 'getaddrinfo',
hostname: 'testing-test-2b746e',
digest: '2404072697'
}
Error: getaddrinfo EAI_AGAIN testing-test-2b746e
at /workspace/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async e (/workspace/.next/server/app/page.js:1:2507)
at async a (/workspace/.next/server/app/page.js:1:2581) {
errno: -3001,
code: 'EAI_AGAIN',
syscall: 'getaddrinfo',
hostname: 'testing-test-2b746e',
digest: '2404072697'
}
Error: getaddrinfo EAI_AGAIN testing-test-2b746e
at /workspace/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async e (/workspace/.next/server/app/page.js:1:2507)
at async a (/workspace/.next/server/app/page.js:1:2581) {
errno: -3001,
code: 'EAI_AGAIN',
syscall: 'getaddrinfo',
hostname: 'testing-test-2b746e',
digest: '2404072697'
}
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: getaddrinfo EAI_AGAIN testing-test-2b746e
at /workspace/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async e (/workspace/.next/server/app/page.js:1:2507)
at async a (/workspace/.next/server/app/page.js:1:2581)
✓ Generating static pages (4/4)
> Export encountered errors on following paths:
/page: /
- Done (17.285s)
- Debug info
- Command failed `npm run build`
exit status: 1
stdout: <see above>
stderr: <see above>
! Failed to execute build script.
!
! The `Heroku Node.js npm Install Buildpack` allows customization of the build process by executing the following scripts if they are defined in `package.json`:
! - `heroku-prebuild`
! - `heroku-build` or `build`
! - `heroku-postbuild`
!
! An unexpected error occurred while executing `npm run build`. See the log output above for more information.
!
! Ensure that this command runs locally without error and retry your build.
ERROR: failed to build: exit status 1
ERROR: failed to build: executing lifecycle: failed with status code: 51
Error ❌
ERROR: failed to build: executing lifecycle: failed with status code: 51
Which area(s) are affected? (Select all that apply)
Application, Docker Compose, Docker
Additional context
I'll pass the repository of an example Next application that accesses the database. It is necessary to set the environment variable in the Dokploy to the database for access. Varaible name: DATABASE_URL
@Siumauricio Do you have any suggestions on how to fix this problem?
I think I also face this issue, so if this is not intentional then it is a huge bug :(
The error is normal to happen, one way to solve it is to use an internal network so that the services can communicate, I know nixpacks has an open issue https://github.com/railwayapp/nixpacks/issues/1057, I do not know if heroku has an option to pass a custom network, the only way to solve that could be using your own custom Dockerfile
@Siumauricio how do you setup an internal network for the app and database to communicate? I don't see anything in Dokploy or the documentation about it
Still no solution @joshfester, the only way is to expose the database to the internet, I have to add some way to pass a custom command to the dockerfile, since nixpacks or heroku doesn't accept custom networks.
Thanks @Siumauricio , would you expect it to work with a Dockerfile or maybe Docker Compose?
https://github.com/docker/buildx/issues/175 and https://github.com/moby/buildkit/issues/978
I think there is no optimal way, according to what I investigated is that you can not specify a network because of buildkit, buildkit uses many caching features, secrets, the only way to solve this problem is disabling DOCKER_BUILDKIT=0 and adding a network flag to the dockerfile builder, because heroku and nixpacks doesn't support networks, but we will lose all those features, at the moment there is no optimal solution, so the only way is exposing the database,
I have been trying with Dockerfile, but the problem is what I said above @joshfester
I think it is more a limitation of docker than of dokploy itself, since dokploy is a very fine wrapper over docker.
@Siumauricio And from your perspective, do you view the exposure of the database as a major security breach or not? Would you recommend going into production with such a database? In comparison with, for example, the Neon project, which allows connection to their remote databases in the same way, everything tells me that this is not a problem, but I would like to hear your opinion.
IMO it is less secure, yes, but I do not consider it as a major breach. There are many companies that sell PostgresQL as a service, and after paying them, they provide us nothing more than a database URL.
I agree with @sangdth , it is less secure as it does not use any encryption, only the security of the database password.
I think implementing encryption to the database I think would be more secure.
I've managed to do it by exposing the database through some port and accessing it with the VPS public IP. For security, I blocked that port with the firewall, so no one could access it from outside.
Also, it would be nice if something could be implemented with https://github.com/railwayapp/nixpacks/pull/1119
Actually that's a very good idea, good solution! @JuanM04
I’m not sure if this could be a solution, but I connected two services within the project by linking them to an external Docker network. I manually created the Docker network on the VPS with docker network create --driver overlay --attachable my_external_network, and then I created each service using a Docker Compose file, attaching them to the previously created external network. The services could see each other normally, and everything works.
Perhaps a good feature would be to allow the creation of external networks within Dokploy that are completely separate from any stack. These networks could then be reusable for other services as needed. Just saying it maybe could be like interesting idea.
I am new to Dokploy, so maybe I am missing something.
Note: None of the services are publicly accessible except through the Traefik reverse proxy.
I've managed to do it by exposing the database through some port and accessing it with the VPS public IP. For security, I blocked that port with the firewall, so no one could access it from outside.
Also, it would be nice if something could be implemented with railwayapp/nixpacks#1119
Thanks for the suggestion. It seems to be working with less configuration and settings.
Looks like the nixpack PR has been merged, although some caveats to note:
- https://github.com/railwayapp/nixpacks/pull/1119#issuecomment-2251372046
In short, using --add-host will automatically add --network=host (necessary for Docker on Linux). You can see this being done here:
- https://github.com/railwayapp/nixpacks/blob/2f5bbf818cf28db2b47697d6cdea8782f0f1b6ea/src/nixpacks/builder/docker/docker_image_builder.rs#L161-L167
Any updates on this ? So It's an issue with the buildpack ?
Any updates on this one? I’m facing the same issue and I don’t want to expose the db publicly.
Hello @raffaele-filiberti Add this to your docker-compose:
networks:
dokploy-network:
external: true
and your service should have this:
api:
image: ghcr.io/blabla:latest
command: node bin/server.js
networks:
- your_other_network_if_exists
- dokploy-network <--- THIS PART REQUIRED
then you will be able to connect your database with internal url
@BatuhanK Thanks, this is the best answer under this thread and deserves more thumb-ups
I am new to dokploy and docker so maybe i am wrong. When using coolify i was able to do this and connect with internal url to my nextjs app using dockerfile deployment. There was no issues with connection url during build time. But when i tried to do the same with dokploy using dockerfile deployment with nextjs there was build time issues when using internal database url.
I dont know if its possible but maybe we can implement a similar strategy that coolify uses for building dockerfiles and make it the default strategy
@ihsanhere do you have a domain configured for your application?
When you add a domain, it automatically adds the app to dokploy-network which will allow you to access your internal database URL. The network is the main point, which you can also verify using docker CLI.
i have added a domain, but still the database is not accessible with internal connection url provided by the databse service. during the build when nextjs runs the collecting page data step it fails with this error
[11:03:24] ERROR: Error: cannot connect to MongoDB. Details: getaddrinfo ENOTFOUND artigence-db-tkllgu
#19 210.5 err: {
#19 210.5 "type": "w",
#19 210.5 "message": "getaddrinfo ENOTFOUND artigence-db-tkllgu",
#19 210.5 "stack":
#19 210.5 MongooseServerSelectionError: getaddrinfo ENOTFOUND artigence-db-tkllgu
#19 210.5 at z (/app/.next/server/chunks/1409.js:56:21893)
#19 210.5 at F.openUri (/app/.next/server/chunks/1409.js:56:29035)
#19 210.5 at async Object.to [as connect] (/app/.next/server/chunks/1409.js:96:5573)
#19 210.5 at async tW.init (/app/.next/server/chunks/1409.js:33:17030)
#19 210.5 at async tJ (/app/.next/server/chunks/1409.js:33:20330)
#19 210.5 at async Object.x [as generateStaticParams] (/app/.next/server/app/(frontend)/[slug]/page.js:1:3217)
#19 210.5 at async builtRouteParams (/app/node_modules/.pnpm/[email protected][email protected][email protected][email protected][email protected]/node_modules/next/dist/build/static-paths/app.js:276:36)
#19 210.5 at async buildAppStaticPaths (/app/node_modules/.pnpm/[email protected][email protected][email protected][email protected][email protected]/node_modules/next/dist/build/static-paths/app.js:246:25)
#19 210.5 at async /app/node_modules/.pnpm/[email protected][email protected][email protected][email protected][email protected]/node_modules/next/dist/build/utils.js:920:79
#19 210.5 at async Span.traceAsyncFn (/app/node_modules/.pnpm/[email protected][email protected][email protected][email protected][email protected]/node_modules/next/dist/trace/trace.js:157:20)
#19 210.5 "reason": {
#19 210.5 "type": "Unknown",
#19 210.5 "servers": {
#19 210.5 "artigence-db-tkllgu:27017": {
#19 210.5 "address": "artigence-db-tkllgu:27017",
#19 210.5 "type": "Unknown",
#19 210.5 "hosts": [],
#19 210.5 "passives": [],
#19 210.5 "arbiters": [],
#19 210.5 "tags": {},
#19 210.5 "minWireVersion": 0,
#19 210.5 "maxWireVersion": 0,
#19 210.5 "roundTripTime": -1,
#19 210.5 "minRoundTripTime": 0,
#19 210.5 "lastUpdateTime": 1440916,
#19 210.5 "lastWriteDate": 0,
#19 210.5 "error": {},
#19 210.5 "topologyVersion": null,
#19 210.5 "setName": null,
#19 210.5 "setVersion": null,
#19 210.5 "electionId": null,
#19 210.5 "logicalSessionTimeoutMinutes": null,
#19 210.5 "maxMessageSizeBytes": null,
#19 210.5 "maxWriteBatchSize": null,
#19 210.5 "maxBsonObjectSize": null,
#19 210.5 "primary": null,
#19 210.5 "me": null,
#19 210.5 "$clusterTime": null,
#19 210.5 "iscryptd": false
#19 210.5 }
#19 210.5 },
#19 210.5 "stale": false,
#19 210.5 "compatible": true,
#19 210.5 "heartbeatFrequencyMS": 10000,
#19 210.5 "localThresholdMS": 15,
#19 210.5 "setName": null,
#19 210.5 "maxElectionId": null,
#19 210.5 "maxSetVersion": null,
#19 210.5 "commonWireVersion": 0,
#19 210.5 "logicalSessionTimeoutMinutes": null
#19 210.5 }
#19 210.5 }
Do i have to manually add any configuration in the Dockerfile for this to work?
Do i have to manually add any configuration in the Dockerfile for this to work?
No - the domain should be sufficient, although you should confirm that both your NextJS app and MongoDB database is connected to dokploy-network (one way of which is by adding a domain and redeploying).
You can check by running this command after you SSH into your host machine:
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Networks}}"
If for whatever reason, the network is not attached automatically to your containers, you can add it manually by running:
docker network connect dokploy-network <YOUR_CONTAINER_ID>
I assume you are using the "database" option when creating your mongodb, but if it's a part of a docker compose YAML file, you can (and should) add the mongodb instance to dokploy-network in the YAML instead, e.g. with
# Under the mongodb service
networks:
- dokploy-network
# At root level
networks:
dokploy-network:
external: true
The problem is that my nextjs initial deplyment is not successfully completed, so it does not show in the list containers when running
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Networks}}"
but i can see the mongodb database container and it has dokploy-network
how to get the initial nextjs deployment to work? I have already added a custom domain.
Try spinning up another container (or just change your docker command temporarily to tail -f /dev/null and redeploy), which will not error out.
You can then
- check that the container is connected to
dokploy-network - exec a shell (terminal session) inside the container and manually confirm the connectivity to your mongo db
Fixing Next.js Database Connection Issue on Dokploy
If your Next.js app is failing to connect to the database on Dokploy using the Internal Connection URL, it's likely because the database isn’t available during the build process. Here’s how to fix it.
Solution
- Use External URL for Build, Internal for Runtime
Modify your.envfile to include both URLs:
DATABASE_URL_EXTERNAL=postgres://user:password@external-db-host/dbname
DATABASE_URL_INTERNAL=postgres://user:password@internal-db-host/dbname
Update next.config.js to switch URLs based on the environment:
module.exports = {
env: {
DATABASE_URL:
process.env.NODE_ENV === "production"
? process.env.DATABASE_URL_INTERNAL
: process.env.DATABASE_URL_EXTERNAL,
},
};
- Ensure the Database is Ready Before Running the App
Add a health check in yourDockerfileto confirm the database is available before starting the application:
HEALTHCHECK --interval=10s --timeout=5s --retries=5 CMD pg_isready -h internal-db-host -U user
- Move Database Calls to Runtime
If your build process includes database queries (for example, ingetStaticProps), move them togetServerSidePropsor an API route so they only run after deployment.
Hey team 👋
One solution for this issue was to use publically exposed external urls. but with this approach if ufw firewall is enabled on the server then the database service is not accessible by default even if it is exposed and we may need to manually change the firewall to allow that port which requires manual configuration of the server.
After investigating the networking issues during builds, I've developed a potential solution. Here's the breakdown:
Problem
- Builds which require connection to other services fail
- Internal services (databases, APIs) become inaccessible during deployment
- No internal network resolution between build containers and dependencies
Root Cause
Docker's default build environment runs in isolation, unable to access dokploy-network services.
Proposed Solution Modified Docker build process to use Buildx with network integration:
-
Buildx Network Integration
docker buildx create --use --name builder-containerd \ --driver docker-container \ --driver-opt network=dokploy-networkCreates a build container within the target network
-
Host Resolution
const hosts = await prepareNetworkHosts("dokploy-network"); commandArgs.push(...hosts.map(h => ["--add-host", h]).flat());Maps internal service names to container IPs
-
Modified Build Command
docker buildx build \ --builder builder-containerd \ --output type=local,name=${appName} \ --add-host service1:internal-ip \ --add-host service2:internal-ip
Validation Tested successfully with: ✅ Next.js + Payload CMS sample app ✅ MongoDB database connection with internal url
Limitations ❗ Only addresses Dockerfile builds (Nixpacks/Heroku Buildpacks need separate solutions) ❗ Requires further testing with multi-service dependencies and deployments
Contribution Offer As someone new to open source:
- I've implemented this in my fork
- Willing to create PR and assist with testing
- Need guidance on contribution workflow and extending this to other build methods
Would the team consider this approach? I'm happy to collaborate on refining it further.
Fixing Next.js Database Connection Issue on Dokploy
If your Next.js app is failing to connect to the database on Dokploy using the Internal Connection URL, it's likely because the database isn’t available during the build process. Here’s how to fix it.
Solution
1. Use External URL for Build, Internal for Runtime Modify your `.env` file to include both URLs:DATABASE_URL_EXTERNAL=postgres://user:password@external-db-host/dbname
DATABASE_URL_INTERNAL=postgres://user:password@internal-db-host/dbnameUpdate
next.config.jsto switch URLs based on the environment:module.exports = { env: { DATABASE_URL: process.env.NODE_ENV === "production" ? process.env.DATABASE_URL_INTERNAL : process.env.DATABASE_URL_EXTERNAL, }, };
2. Ensure the Database is Ready Before Running the App Add a health check in your `Dockerfile` to confirm the database is available before starting the application:HEALTHCHECK --interval=10s --timeout=5s --retries=5 CMD pg_isready -h internal-db-host -U user
3. Move Database Calls to Runtime If your build process includes database queries (for example, in `getStaticProps`), move them to `getServerSideProps` or an API route so they only run after deployment.
To Reproduce
After I created the Next application and deployed it to Dokploy and connected to the Dokploy database (PostgreSQL), communication works if I connect via an external connection string, but when I change that connection string to internal in the environment, then the build of Next application crashes.
Current vs. Expected behavior
I expect to have a connection to the database through internal communication on the server and not through the Internet. I see internet connect to databse as a huge security flaw.
Provide environment information
Ubuntu, Hetzner cax11 4gb.
Error in dokploy after I made change in ENV from external to internal connection string...
Initializing deployment Build heroku_buildpacks: ✅ Source Type: github: ✅ 24: Pulling from heroku/builder Digest: sha256:11c05fd10f421614227b72ad21c5e0d44ca3ca1a3e1f6592da92f039e09d33f9 Status: Image is up to date for heroku/builder:24 24: Pulling from heroku/heroku Digest: sha256:b2e3a768f6a89d3c47def9bda468b15eb9ba66ca4973e05546417b99bdefe94a Status: Image is up to date for heroku/heroku:24 ===> ANALYZING Restoring data for SBOM from previous image ===> DETECTING 2 of 5 buildpacks participating heroku/nodejs-engine 3.2.14 heroku/nodejs-npm-install 3.2.14 ===> RESTORING Restoring metadata for "heroku/nodejs-engine:web_env" from app image Restoring metadata for "heroku/nodejs-engine:dist" from app image Restoring metadata for "heroku/nodejs-engine:node_runtime_metrics" from app image Restoring metadata for "heroku/nodejs-npm-install:npm_runtime_config" from app image Restoring metadata for "heroku/nodejs-npm-install:npm_cache" from cache Restoring data for "heroku/nodejs-engine:dist" from cache Restoring data for "heroku/nodejs-npm-install:npm_cache" from cache ===> BUILDING
[Heroku Node.js Engine Buildpack]
[Checking Node.js version] Node.js version not specified, using 20.x Resolved Node.js version: 20.17.0
[Installing Node.js distribution] Reusing Node.js 20.17.0 (linux-arm64) Installing application metrics scripts
Heroku Node.js npm Install Buildpack
- Installing node modules
Using npm version
10.8.2Restoring npm cache
Configuring npm cache directory
Running
npm ci "--production=false"npm warn config production Use
--omit=devinstead.added 52 packages, and audited 53 packages in 6s
3 packages are looking for funding run
npm fundfor detailsfound 0 vulnerabilities
Done (6.321s)
- Running scripts
Running
npm run build[email protected] build next build
Attention: Next.js now collects completely anonymous telemetry regarding usage. This information is used to shape Next.js' roadmap and prioritize features. You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL: https://nextjs.org/telemetry
▲ Next.js 14.2.13 Creating an optimized production build ...✓ Compiled successfully Linting and checking validity of types ... Collecting page data ... Generating static pages (0/4) ... Generating static pages (1/4)
Generating static pages (2/4) Generating static pages (3/4)Error: getaddrinfo EAI_AGAIN testing-test-2b746e at /workspace/node_modules/pg-pool/index.js:45:11 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async e (/workspace/.next/server/app/page.js:1:2507)
The best solution I found was this:
Change your Dockerfile so it doesn’t run npm run build during the image build.
In Dokploy, go to Advanced → Run Command for your app and set it to:
pnpm run build && npm start
This way, Next.js builds after the container starts — when MongoDB (or any other internal service) is already running on the internal network. It fixed the connection issue for me without having to expose MongoDB externally.
Both my webapp and database containers are attached to the same dokploy-network. I can also connect to the database from a separate debug container on that network, but my application still throws a similar connection error as above during building.
Perhaps a solution that can implemented by Dokploy to configure buildkit to spawn its own dokploy-network connected container so the builder will have access to the dokploy-network internal resources and absolve the error during building.
It should be trivial enough if Dokploy can just bootstrap its own buildx builder (which has the --driver-opt network flag set to dokploy-network, and have a dropdown in the UI to select the builder per application. Just make the dropdown conditional, based on the build type if necessary, and It should address this issue?
The solution really cannot be, expose your database publicly to the internet. That is not good security practice at all, and just because Neon and others do it (because not everyone is going to setup a peering link with them), doesn't make it acceptable.