Search code examples
dockernginxshinyreverse-proxylets-encrypt

Running shiny app through nginx and letsencrypt ssl using docker


I would like to run my app (myapp) on my domain (www.myapp.com) through nginx reverse proxy and letsencrypt ssl using docker. Everything looks right, but I can't see my app running on my domain.

If I run my docker app without using the reverse proxy and SSL, I can see my app running on my domain.

I have done the following:

  1. Running the proxy
$ cd
$ mkdir certs

$ docker run -d -p 80:80 -p 443:443 \
    --name nginx-proxy \
    -v $HOME/certs:/etc/nginx/certs:ro \
    -v /etc/nginx/vhost.d \
    -v /usr/share/nginx/html \
    -v /var/run/docker.sock:/tmp/docker.sock:ro \
    --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true \
    jwilder/nginx-proxy

  1. Running the Let's Encrypt companion container:
$ docker run -d \
    --name nginx-letsencrypt \
    --volumes-from nginx-proxy \
    -v $HOME/certs:/etc/nginx/certs:rw \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    jrcs/letsencrypt-nginx-proxy-companion

  1. My app dockerfile:
# get shiny server and R from the rocker project
FROM rocker/shiny:4.0.5

RUN apt-get update && apt-get install -y \
    sudo \
    gdebi-core \
    pandoc \
    pandoc-citeproc \
    libcurl4-gnutls-dev \
    libxt-dev \
    libssl-dev \
    libxml2 \
    libxml2-dev \
    libsodium-dev

# install R packages required 
# Change the packages list to suit your needs
RUN R -e "install.packages(c('shiny', 'shinythemes', 'dygraphs', 'shinyWidgets', 'manipulateWidget', 'DT', 'zoo', 'shinyjs','emayili', 'wordcloud2', 'rmarkdown', 'xts', 'shinyauthr', 'curl', 'jsonlite', 'httr'), repos='http://cran.rstudio.com/')"

# copy the app directory into the image
WORKDIR /srv/shiny-server/myapp/app
COPY app .

# run app
EXPOSE 80
CMD ["R", "-e", "shiny::runApp('/srv/shiny-server/myapp/app',  host = '0.0.0.0', port = 8080)"]


  1. Finally, I have built and run my docker app:
$ cd /srv/shiny-server/myapp
$ sudo docker build -t myapp .

$ docker run -d \
    --name mysite \
    -e '[email protected]' \
    -e 'LETSENCRYPT_HOST=myapp.com' \
    -e 'VIRTUAL_HOST=myapp.com' myapp

Unfortunately, when I visit my domain, I see a page with the message:

http://myapp.com -> 502 Bad Gateway nginx/1.21.6

https://myapp.com -> 500 Internal Server Error nginx/1.21.6

I can't see my app running.

If I run the following, after running the nginx-proxy and nginx-letsencrypt containers,

$ docker run -d \
    --name nginx \
    -e '[email protected]' \
    -e 'LETSENCRYPT_HOST=myapp.com' \
    -e 'VIRTUAL_HOST=myapp.com' nginx

I can see:

http://myapp.com -> Welcome to nginx!

https://myapp.com -> 500 Internal Server Error nginx/1.21.6

If I just run the nginx-proxy and the nginx-letsencrypt containers, I get the following:

http://myapp.com -> 503 Service Temporarily Unavailable nginx

https://myapp.com -> 503 Service Temporarily Unavailable nginx


Solution

  • Perhaps here are multiple problems.

    1. Port
      In your Dockerfile, you wrote EXPOSE 80 and after that you start shiny with port 8080.
      You should write EXPOSE 8080 instead. When you start your app-container, then you might must specify VIRTUAL_PORT.

    2. SSL Certs
      I think, that nginx is not happy about the certs. A 500 always means, that there is a problem on server-side.
      Have a look in the logs of nginx (docker logs nginx-proxy).
      In general, I recommend to avoid dockerized certs (they are pretty complex and often cause erros). Have look at point 4 of my other answer: Can't enable ssl by docker-letsencrypt-nginx-proxy-companion

    3. Unused mounts
      Maybe I am wrong, but I think that some volumes are not necessary. Like -v /etc/nginx/vhost.d.

    Good luck.