TheYuwana
Phoenix app in docker with ssl not receiving anything on port 443
Hey there fellow devs,
For the love of everything, I can’t seem to get this to work… I have a docker container with a phoenix app running in there. It’s hosted on a subdomain “sub.example.com” and I need to serve it with https.
So I got myself a wildcard SSL certificate, installed it, configured the production file and exposed 80 and 443 ports of the docker container.
Tried it out and port 80 works fine, but 443 is always returning a “ERR_CONNECTION_RESET”. The logs is showing nothing on 443, but 80 works fine.
Been trying for awhile now, and now i need your help. Any idea on whats wrong? Check the code below:
Dockerfile
FROM bitwalker/alpine-elixir-phoenix:latest
# create app folder
RUN mkdir /app
WORKDIR /app
COPY . .
# setting the port and the environment (prod = PRODUCTION!)
EXPOSE 80
EXPOSE 443
# install dependencies (production only)
RUN mix local.rebar --force
RUN mix deps.get --only prod
RUN mix compile
prod.exs
config :example, ExampleWeb.Endpoint,
http: [port: 80],
url: [host: "sub.example.com"],
cache_static_manifest: "priv/static/cache_manifest.json",
https: [
cipher_suite: :strong,
otp_app: :example,
port: 443,
keyfile: System.get_env("SSL_KEY_PATH"),
certfile: System.get_env("SSL_CERT_PATH"),
cacertfile: System.get_env("SSL_CHAINED_CERT_PATH")
]
curl https://sub.example.com/ --verbose result:
* Trying 64.225.24.82...
* TCP_NODELAY set
* Connected to sub.example.com (64.225.24.82) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to sub.example.com:443
* Closing connection 0
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to sub.example.com:443
Marked As Solved
TheYuwana
Alright, after days of searching, trial and error and discussions on this post. It finally works with the following configurations! Thanks to everyone and especially @egze with helping out and sparring!
Btw both nginx and phoenix are in the same docker conatiner.
Phoenix - prod.exs
config :example, ExampleWeb.Endpoint,
http: [port: 5000],
url: [host: "sub.example.com", port: 5000]
nginx config
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name sub.example.com;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/nginx/ssl/example_chained.pem;
ssl_certificate_key /etc/nginx/ssl/example.pem;
large_client_header_buffers 4 16k;
location ~ live/websocket {
proxy_http_version 1.1;
proxy_set_header Origin '';
proxy_set_header X-Forwarded-Host $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_ssl_server_name on;
proxy_pass http://0.0.0.0:5000;
break;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_ssl_server_name on;
proxy_pass http://0.0.0.0:5000;
break;
}
}
Also Liked
egze
Something else to think about is to let Nginx or other web server handle the SSL part, and proxy_pass requests to upstream. Then you can just run your Phoenix app on port 4000 and not worry about configuring ssl in Phoenix.
This is how I run my phoenix site with nginx in between.
upstream myapp {
server localhost:4000;
}
server {
server_name myapp.de;
listen 443 ssl http2;
listen [::]:443 ssl http2 ipv6only=on;
ssl_certificate /etc/letsencrypt/live/myapp.de/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/myapp.de/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
client_max_body_size 50m;
location ~* \.(eot|ttf|woff)$ {
add_header Access-Control-Allow-Origin *;
}
location ~* ^.+\.(css|js|ico|jpg|jpeg|png|svg|woff|woff2)$ {
root /var/www/apps/myapp.de/current/lib/myapp-0.1.0/priv/static;
etag off;
expires max;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control public;
}
location ~ live/websocket {
proxy_http_version 1.1;
proxy_set_header Origin '';
proxy_set_header X-Forwarded-Host $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://myapp;
break;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://myapp;
break;
}
}
stefanchrobot
How are you running the container? EXPOSE doesn’t do anything, really:
EXPOSE
EXPOSE <port> [<port>/<protocol>...]
The
EXPOSEinstruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified.
The
EXPOSEinstruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the-pflag ondocker runto publish and map one or more ports, or the-Pflag to publish all exposed ports and map them to high-order ports.
egze
Because you can also use pure Erlang/Elixir to host your site if you want. SSL can certainly be done with pure Phoenix. Just that for me it’s not so practical. I host multiple sites on one box and I only have one 443 port ![]()
Popular in Questions
Other popular topics
Latest Phoenix Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security










