Search code examples
nginxmonodockerfastcgifastcgi-mono-server

fastcgi-mono-server4 and nginx with docker


A lot of information on the web tells how to set up nginx + fastcgi-mono-server4 on the same machine to host ASP.net (at the moment I'm using F# application with Websharper) from linux environment. But docker should run only one process. Also there are solutions around that with using runit or other tools to run nginx and mono server on the same container.

I got it working in the same container, but when I try to move web application + fastcgi-mono-server4 to another container, I got

 [error] 12#12: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.99.1, server: , request: "GET / HTTP/1.1", upstream: "fastcgi://172.17.0.40:32775", host: "192.168.99.100:32786"

Found an article about similar requirements but for php fastcgi server (php-fpm), and that works with just linking containers. But for fastcgi-mono-server4 it doesn't.

I have tried creating 1 container with fastcgi-mono-server4 + application files, exposing a VOLUME of application files, exposing port 9000 and then nginx container with volumes from first container and link to it Also tried to run 2 same containers with nginx and mono server installed, first with fastcgi_pass 127.0.0.1:9000, second with fastcgi_pass 172.17.0.40:32775 - ip and port from first container. If accessing first container - application works, accessing second container - same error as above.

Comand used to run mono server:

fastcgi-mono-server4 /printlog=True /applications=/:/var/www/websharper/ /socket=tcp:0.0.0.0:9000 /loglevels=All /verbose=True

Versions of installed software:

Container from mono (debian wheezy with mono:4.0.0)
NGINX_VERSION 1.9.5-1~wheezy
$ mono --version
Mono JIT compiler version 4.0.3 (Stable 4.0.3.20/d6946b4 Tue Aug  4 09:43:57 UTC 2015)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
    TLS:           __thread
    SIGSEGV:       altstack
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none
    Misc:          softdebug
    LLVM:          supported, not enabled.
    GC:            sgen
$ fastcgi-mono-server4 --version
Mono.WebServer2.dll 0.4.0.0

Some logs from fastcgi-mono-server4 startup

9: 1 fastcgi-mono-server [2015-10-01 09:01:17.510407] Debug  : fastcgi-mono-server4
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.530481] Debug  : Uid 0, euid 0, gid 0, egid 0
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.531310] Debug  : Root directory: /
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.532843] Notice : Adding applications '/:/var/www/websharper/'...
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.533478] Notice : Registering application:
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.533757] Notice :     Host:          any
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.534075] Notice :     Port:          any
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.534459] Notice :     Virtual path:  /
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.534770] Notice :     Physical path: /var/www/websharper/
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.543250] Debug  : Parsed tcp:0.0.0.0:9000 as URI tcp:0.0.0.0:9000
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.556826] Debug  : Listening on port: 9000
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.558991] Debug  : Listening on address: 0.0.0.0
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.564079] Debug  : Max connections: 1024
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.564786] Debug  : Max requests: 1024
9: 1 fastcgi-mono-server [2015-10-01 09:01:17.565224] Debug  : Multiplex connections: False
9: 3 fastcgi-mono-server [2015-10-01 09:01:17.568840] Debug  : Server started [callback: Mono.WebServer.FastCgi.ServerProxy]

On top of mono:4.0.0 docker image installed:

apt-get install -y ca-certificates nginx=1.9.5-1~wheezy
apt-get install -qy mono-fastcgi-server4
apt-get install -qy mono-xsp4
apt-get install -qy fsharp

Also I'm ensuring that mono 4.5 is used for the application:

sed -ie 's|mono/4.0|mono/4.5|g' /usr/bin/fastcgi-mono-server4 \
&& sed -ie 's|mono/4.0|mono/4.5|g' /usr/bin/xsp4

And my nginx.conf

worker_processes  1;
events {
   worker_connections  1024;
}
http {
   include       mime.types;
   default_type  application/octet-stream;
   sendfile        on;
   keepalive_timeout  65;
   server {
       listen       80 default;
       access_log   /dev/stdout;
       error_log    /dev/stdout;
       root         /var/www/websharper;
       index        main.html;
       location / {
           root                /var/www/websharper/;
           fastcgi_pass        172.17.0.40:32775;
           include             /etc/nginx/fastcgi_params;
       }
       error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }
   }
}

and finally fastcgi_params

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
fastcgi_param  PATH_INFO         "";
fastcgi_param  SCRIPT_FILENAME   $document_root$fastcgi_script_name;

Update:

I have found in sources that TcpSocket is assigning Loopback ip if you choose Any ip... which is weird...

class TcpSocket : StandardSocket {
    public TcpSocket (System.Net.IPEndPoint localEndPoint)
        : base (System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream,
                System.Net.Sockets.ProtocolType.IP, localEndPoint)
    {
    }

    public TcpSocket (System.Net.IPAddress address, int port)
        : this (new System.Net.IPEndPoint (Equals(address, System.Net.IPAddress.Any) ?
            System.Net.IPAddress.Loopback : address, port))
    {
    }
}

Anyway I have tried to use set ip address directly for mono server(by linking nginx container to mono container)

fastcgi-mono-server4 /printlog=True /applications=/:/var/www/websharper/ /socket=tcp:$(printenv NGINX_HOST_PORT_80_TCP_ADDR):9000 /loglevels=All /verbose=True

and running the box with

docker run --name t2 --link t1:nginx_host -it -P vasylpurchel/docker-websharper

where t1 is a box with nginx running in it This test also failed with:

root@dc540db6577f:/#     8: 1 fastcgi-mono-server [2015-10-02 14:32:05.147774] Debug  : fastcgi-mono-server4
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.154128] Debug  : Uid 0, euid 0, gid 0, egid 0
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.155000] Debug  : Root directory: /
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.156562] Notice : Adding applications '/:/var/www/websharper/'...
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.157182] Notice : Registering application:
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.157457] Notice :     Host:          any
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.157908] Notice :     Port:          any
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.158195] Notice :     Virtual path:  /
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.158489] Notice :     Physical path: /var/www/websharper/
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.169995] Debug  : Parsed tcp:172.17.0.5:9000 as URI tcp:172.17.0.5:9000
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.181117] Debug  : Listening on port: 9000
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.182573] Debug  : Listening on address: 172.17.0.5
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.186638] Debug  : Max connections: 1024
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.187418] Debug  : Max requests: 1024
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.187767] Debug  : Multiplex connections: False
8: 1 fastcgi-mono-server [2015-10-02 14:32:05.192868] Error  : Failed to start server Mono.WebServer.FastCgi.Sockets.    TcpSocket: The requested address is not valid in this context (10049)
Unhandled Exception:
System.Net.Sockets.SocketException: The requested address is not valid in this context
at System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end) [0x00000] in <filename unknown>:0
at Mono.WebServer.FastCgi.Sockets.StandardSocket.Listen (Int32 backlog) [0x00000] in <filename unknown>:0
at Mono.WebServer.FastCgi.GenericServer`1[Mono.WebServer.FastCgi.ConnectionProxy].Start (Boolean background, Int32 backlog) [    0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException: The requested address is not valid in this context
at System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end) [0x00000] in <filename unknown>:0
at Mono.WebServer.FastCgi.Sockets.StandardSocket.Listen (Int32 backlog) [0x00000] in <filename unknown>:0
at Mono.WebServer.FastCgi.GenericServer`1[Mono.WebServer.FastCgi.ConnectionProxy].Start (Boolean background, Int32 backlog) [0x00000] in <filename unknown>:0

Address 172.17.0.5 was an IpAddress of container with nginx running on.


Solution

  • The fastcgi-mono-server4 has a limitation on docker container with the listening address when you use the parameter

    • /socket=tcp:9000 only listen in localhost
    • /socket=tcp:0.0.0.0:9000 only listen in localhost, weird but true

    to fix the fastcgi-mono-server4 behavior, you have to use the docker container IP address in socket parameter

    • /socket=tcp:IPContainer:9000
    • /socket=tcp:$(ip -4 addr show eth0| grep -Po 'inet \K[\d.]+'):9000

    you need to fix the command inside the Docker container

    fastcgi-mono-server4 /applications=/:/var/www/websharper/ /socket=tcp:$(ip -4 addr show eth0| grep -Po 'inet \K[\d.]+'):9000
    

    This is an example the Dockerfile fixed

    FROM mono:latest
    
    RUN apt-get update
    RUN apt-get install -y mono-fastcgi-server4
    RUN rm -rf /var/lib/apt/lists/* /tmp/*
    
    RUN echo "#!/bin/sh\nfastcgi-mono-server4 /applications=/:/var/www/websharper/ /socket=tcp:\$(ip -4 addr show eth0| grep -Po 'inet \K[\d.]+'):9000" > /opt/mono-fastcgi
    RUN chmod +x /opt/mono-fastcgi
    
    EXPOSE 9000
    
    CMD [ "/opt/mono-fastcgi" ]