Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Container ports are reassigned upon restart #31

Closed
dmartin opened this issue Oct 27, 2021 · 3 comments
Closed

Container ports are reassigned upon restart #31

dmartin opened this issue Oct 27, 2021 · 3 comments

Comments

@dmartin
Copy link
Contributor

dmartin commented Oct 27, 2021

Challenge containers are launched with an always restart policy, but unfortunately Docker reassigns host ports upon restart when an explicit port mapping is not specified up front. This causes the port information in the database to become inaccurate if a container restarts.

For example:

$ cd ~/cmgr/examples

$ ../bin/cmgr update
# [...]

$ ../bin/cmgr build cmgr/examples/flask--sqlite 1
# Build IDs:
#    1

$ ../bin/cmgr start 1
# Instance ID: 1

$ docker container ls --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}"
# CONTAINER ID   IMAGE                                     PORTS
# fad446c0acdf   cmgr/examples/flask--sqlite:1-challenge   0.0.0.0:61285->5000/tcp

$ docker restart fad446c  # same behavior if automatically restarted
# fad446c

$ docker container ls --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}"
# CONTAINER ID   IMAGE                                     PORTS
# fad446c0acdf   cmgr/examples/flask--sqlite:1-challenge   0.0.0.0:61323->5000/tcp
@jrolli
Copy link
Contributor

jrolli commented Oct 27, 2021

@dmartin, I think I'm leaning toward the idea of fixing this by allowing an explicit port range to be configured for challenge ports (likely via an environment variable). If the configuration is set, then cmgr/cmgrd will assume they fully control assignments in that port range and manage it through querying the database. If it is not set, then it continues to use the current behavior (delegating to Docker and using ephemeral ports). It would end up being a larger change, but I think is needed to avoid racing with other connections. Thoughts?

@dmartin
Copy link
Contributor Author

dmartin commented Oct 27, 2021

@jrolli, I think that works. Perhaps it should also be mentioned in the documentation to adjust /proc/sys/net/ipv4/ip_local_port_range to exclude the block carved out for challenges, so that other applications' attempts to bind an ephemeral port don't land within the cmgr range (some services like dockerd etc. would need to be restarted as well, as it looks like they only read the ephemeral port range once upon init.)

An aside: looking into this sent me down a rabbit hole of looking into how Docker actually allocates ephemeral ports, which turns out to be... pretty poorly? If I'm understanding correctly, they don't use bind(2) to get an available port at all, but just maintain their own map and hope for the best. Actually asking the OS for an available port has been a TODO for 7 years(!)

jrolli pushed a commit that referenced this issue Oct 29, 2021
This addresses the issue of an instances ports changing on restart
by providing a configuration knob to assign ports to `cmgr`.  If
the `CMGR_PORTS` environment variable is present, `cmgr` will
assume that it has the ability to fully control/assign the ports
in this range without further coordination with the OS or another
process.  This allows it to assign a port number to instances before
creating the instance with Docker which then enables Docker to keep
the same port between restarts of the same container.

Supersedes #31
Fixes #32
@jrolli
Copy link
Contributor

jrolli commented Oct 29, 2021

Fixed in v0.11.1

@jrolli jrolli closed this as completed Oct 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants