'How do I both expose the port on a container to the local host AND bind persistent data to the container?
I am using dockerode to create a new PostgreSQL docker container. I want to be able to:
- Expose port
5432on the local host - Have the container use a directory on the local host as the persistent data store
I've been able to get a working implementation that creates a Docker container and exposes port 5432 on the local host with the following code:
docker.createContainer({
Image: "postgres",
Env: [`POSTGRES_PASSWORD=postgres`],
HostConfig: {
PortBindings: {
"5432/tcp": [{ HostPort: "5432" }]
},
},
ExposedPorts: {
"5432/tcp": {}
},
name: "container-name"
})
- In this implementation, the data is not persistent - restarting the container will always start from a "fresh" DB
- I need to have persistent data
From reading the Docker REST API documentation (and through reading lots of community posts), I found that I need to use the Binds parameter. I updated my code to the following:
docker.createContainer({
Image: "postgres",
Env: [`POSTGRES_PASSWORD=postgres`],
HostConfig: {
PortBindings: {
"5432/tcp": [{ HostPort: "5432" }]
},
// NEW CODE
Binds: [
"/path/on/host/machine:/path/on/container"
],
},
ExposedPorts: {
"5432/tcp": {}
},
name: "container-name"
})
- However, after adding the
Bindsparameter, I am no longer able to connect to the database from the host machine
Can anyone tell me what I am doing wrong here? I can't figure out what Binds needs to be in this particular setup. Eventually, I won't need the database exposed to the local machine, but for now, I need to be able to for testing purposes. Thanks in advance!
UPDATE 1 - 6/15/2019
I retested this with a similar setup as suggested, which really wasn't all that different from what I was already doing. However, the suggestions helped me get on the right track and understand where my error was.
It seems that the problem was happening because I was trying to reuse a directory on my local host that had already been used for a different database setup. I thought this was supported; I'm guessing there is something I am missing?
In either case, I have this working now, but I don't quite get why I can't reuse the same directory on my host machine that I was using when I start the containers from the command line.
Clarification
I failed to mention that I can get this working by starting the container from the command line. The problem is when trying to use dockerode - however, I don't think this is a problem with Dockerode, but rather with some misunderstanding I have with the Docker REST API.
I can use the same directory for all databases IF I started the containers from the Command line, but not if I start the containers using the Docker REST API (dockerode in my case).
UPDATE 2 - 6/15/2019
It seems there was something wrong with the path my code was generating. After I went through this a bit, it seems I simply overlooked that error. Strangely, I didn't get any errors in the container when I checked the logs - that's why I didn't think there was anything wrong with the path.
So, for those who encounter this, it may be a simple matter of needing to fix the path you referenced on the host machine.
With that being said, I've marked the accepted solution by mchawre - his solution was correct for the original question I asked. The rest of the issues I had were due to a bug, it seems.
(I do wish the Docker logs would have said something like "no such directory" for the container when it started, though - that would have led to a much-quicker resolution)
Relevant Info I found the following info here:
Warning: the Docker specific variables will only have an effect if you start the container with a data directory that is empty; any pre-existing database will be left untouched on container startup.
- I think this is why I hit this issue, but not 100% sure yet
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
