Closed ltalirz closed 1 year ago
Haven't read through this, but my thought process here is that we should simplify port handling such that we drop anything that isn't managed by the proxy
plugin.
Haven't read through this, but my thought process here is that we should simplify port handling such that we drop anything that isn't managed by the proxy plugin.
As someone who isn't familiar with how dokku works internally, it would be helpful if you could elaborate a bit on this. I.e. which currently active mechanisms of port handling do you suggest to drop/replace? Where should one look in order to fix this?
About this issue itself: it would be great if others could comment whether they observe the same behavior?
Since this potentially affects anybody using Dockerfile
s for deployment I would be surprised if I was the only one experiencing this (or something about our setup must be very special).
DOKKU_DOCKERFILE_PORTS
Remove stuff like that (and PROXY_SSL_PORT) in favor of just whatever is settable by the proxy plugin. Proxying and domain handling is quite "rough" in Dokku atm (lots of hooks to jack into/support), which makes debugging/feature development difficult.
If I understand correctly, this would mean an extra step users need to keep in mind when deploying any app that uses Dockerfile
s and doesn't serve on the default port 5000.
I.e. something like
ssh -t dokku@materialscloud.io proxy:ports-set seekpath https:443:80
I wonder how many people will forget this and complain that the app isn't working... perhaps one could show a hint about this on the error page that dokku displays when the container isn't reachable?
On the other hand, the behavior of EXPOSE XX
can be non-obvious as well, since it can be inherited from parent images (that's from the docker perspective, not sure whether dokku's handling of the directive works that way as well).
I.e. in principle the base image might decide to no longer EXPOSE
a port and break your app (or it may EXPOSE
ports you don't want to expose, and there is currently no way to "unexpose" in docker).
P.S. If the automatic configuration of the port mapping is dropped, it would become very useful to be able to at least configure the default target for the port mapping - in case your dokku instance typically receives apps that are listening on a port other than 5000.
What I'd like to do is separate the automatically detected ports from the ones manually set. So if you don't specify overrides, we'll detect on deploy and set those as some "autodetected" versions somewhere. We'll use the current detected proxy ports as is, but otherwise new apps will be autodetected, and when someone force sets ports, we'll let them know that they will need to force override them later (so no weirdness around your values being overriden).
I'm not sure I follow 100% but keeping a record of autodetected ports separately and warning about manual overrides sounds like a great approach. Happy to help test / review any PRs in this direction.
About this issue itself: it would be great if others could comment whether they observe the same behavior?
@ltalirz Yeah we have this all the time with Dockerfile
deployments ;-) Known/current solution is to after initial deploy manually fix the proxy ports. We have always sort of accepted this (sic).
I would definitely like that a Dockerfile
deployment actually gets a correct proxy configuration.. removing the extra manual proxy cmd requirement.
Another same kind of issue is when an app changes its internal ports.. i.e. was first an app that listened internally on 5000 (expressjs?).. then the app was updated and listens internally on 3000 (nextjs?)... in this case we (DevOps) know we need to change the proxy ports.. though for this case it may be nicer to add extra port info to the, sort of unused, app.json or such like? Though I am diluting the issue with this.
@ltalirz I also think that when using Dockerfile
deployment it is up to the DevOp to decide if the app should be exposed via the proxy... Using a Dockerfile deployment entails extra config. Some Dockerfile
deployments may not want to be exposed via http... just linked to other apps... ? Think elasticsearch or suchlike..
Though I will give a simple idea a go for honouring the get_dockerfile_exposed_ports
(which is the first found exposed port according to the code)...
sort of a kind of an idea:
# extract first port from Dockerfile
local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile)
if [[ -n "$DOCKERFILE_PORTS" ]]; then
config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS"
# Check: app is exposed?/app has http?/app has proxy?
# Check: detected port is something we want to expose via the proxy? 80/8000/8080/3000(nextjs lots of js stuff)/5000(expressjs?) ?
# WARN this may break stuff... who knows who or what is the first port?
config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="http:80:$DOCKERFILE_PORTS"
# TODO has TLS then also add proxy https mapping.. `https:443:x`
#config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="http:80:$DOCKERFILE_PORTS https:443:$DOCKERFILE_PORTS"
fi
Possibly with a warning if it is a non, known (sic), "http" port.. so just do it for 80/8000/8080/3000(nextjs lots of js stuff)/5000(expressjs?) ? and ignore others? Again not all Dockerfile deployments are exposed http apps...
Better would be just doing this for port 80 (most probable a website) and otherwise document to utilize something like app.json/dokku/port-mapping
when using the Dockerfile deployment feature?
Hi @AubreyHewes, @josegonzalez mentioned above that he would prefer removing DOKKU_DOCKERFILE_PORTS
entirely - perhaps he would be willing to give a few more concrete pointers on which parts of the code should be changed, and in what way? (+ perhaps some hints on new variable naming, if we need to introduce any)
Related observation:
When deploying an app via docker image and attaching it to a dokku network the original port for the apps Network web listeners
does not get updated when the app's exposed port changes in the docker image. Using dokku network:report
will always show the original port in the line for Network web listeners
, even though the new port is being used as expected.
I agree Dokku's proxy doesn't work with EXPOSE, but the actually bad thing is that EXPOSE does change the behavior. So if you have a Dockerfile with EXPOSE (which, you can't remove if you inherited it from a parent image), you get stuck in a halfway state after deploying image, and you can't solve it without manually changing the proxy config.
To work around it, I ended up writing my nginx Dockerfile like this:
FROM nginx:stable-alpine
EXPOSE 5000
ENV PORT=5000
COPY installation/docker.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/static /usr/share/nginx/html
Then I made my docker.conf.template
respect the PORT variable:
server {
listen ${PORT};
# ...
So now even though Dokku wants to proxy 5000 despite the EXPOSE 80, by just exposing 5000 it works correctly now on the first deployment without any additional configuration.
If you want to see it in context, the full MR is here: https://gitlab.com/soapbox-pub/soapbox-fe/-/merge_requests/1468
As a Dokku newbie this caused a lot of confusion for me, I was getting a "We're sorry, but something went wrong." error and couldn't figure out what was wrong with my setup, until I eventually stumbled into this issue.
Until this bug is fixed, would you consider mentioning it in the documentation in the meantime? Currently, the documentation is not consistent with the actual behavior of Dokku.
Closing as there is a pull request open.
In the pull request:
If I get time, I'll also add the following:
PORT
value (this will be autodetected from the port mapping during a build) via the ports pluginDOKKU_PROXY_PORT
and DOKKU_PROXY_SSL_PORT
via the ports plugin (currently they are env vars)
Description of problem
Pushing a git repository containing a
Dockerfile
that doesEXPOSE 80
. This is recognized by dokku as evidenced by the logs during the push:Reading the dokku documentation, I expect that this will cause dokku to map the corresponding port on the remote.
However, when I then inspect the app on the dokku instance, the port mappings are not set up correctly - in particular, port 80 is still mapped to the default port 5000 inside the container:
How reproducible
I've tried
dokku apps:destroy seekpath
and recreating it againdokku proxy:build-config seekpath
commandand keep getting the same result. The only solution I found is to manually set the corresponding port mapping.
Steps to Reproduce
git clone https://github.com/materialscloud-org/tools-seekpath/
git remote add dokku@yourdokku:appname
dokku proxy:ports appname
Actual Results
Expected Results
Following the dokku documentation, I may need another
EXPOSE 443
, which would then result in mapping port 443:443. In any case, the configuration above is the mapping that I would like to have.Environment Information
dokku report APP_NAME
outputHow (deb/make/rpm) and where (AWS, VirtualBox, physical, etc.) was Dokku installed?:
Installed via ansible-dokku role using latest versions , see PR https://github.com/dokku/ansible-dokku/pull/76