title: How to create a server in Mathematica container?
body: <p>I try to create a server in a Docker container using Wolfram Language. Docker parameters and Wolfram script, which starts a server inside it, are in the attached files:</p>
  <ul>
  <li><code>docker-compose.yml</code></li>
  </ul>
  <pre class="lang-yaml prettyprint-override"><code>services:
    wm:
      build: .
      volumes:
        - .:/app:ro
      ports:
        - &quot;61104:8000&quot;
      restart: on-failure
      hostname: wm
      container_name: wm
      working_dir: /app
      entrypoint: wolframscript -file /app/tcp_server.wls
  </code></pre>
  <ul>
  <li><code>Dockerfile</code></li>
  </ul>
  <pre><code>FROM ubuntu:20.04
  
  ENV DEBIAN_FRONTEND noninteractive
  ENV DEBCONF_NONINTERACTIVE_SEEN true
  
  RUN apt update -yq \
      &amp;&amp; apt install -yq xz-utils curl gcc tzdata musl-dev python3-dev python3-pip clang \
      &amp;&amp; dpkg-reconfigure tzdata \
      &amp;&amp; apt install -y avahi-daemon wget sshpass sudo locales \
      locales-all ssh nano expect libfontconfig1 libgl1-mesa-glx libasound2 \
      build-essential mosquitto mosquitto-clients libnss-mdns mdns-scan nodejs \
      &amp;&amp; apt clean \
      &amp;&amp; apt autoremove -y \
      &amp;&amp; echo &quot;en_US.UTF-8 UTF-8&quot; &gt; /etc/locale.gen &amp;&amp; locale-gen
  
  COPY ./Mathematica_12.1.1_LINUX.sh /root/
  
  WORKDIR /root
  
  RUN ./Mathematica_12.1.1_LINUX.sh --target ./extract --nox11 -- -auto -nodesktop \
      &amp;&amp; systemctl enable avahi-daemon \
      &amp;&amp; echo '!10.55.229.55' &gt; /usr/local/Wolfram/Mathematica/12.1/Configuration/Licensing/mathpass
  </code></pre>
  <ul>
  <li><code>tcp_server.wls</code></li>
  </ul>
  <pre class="lang-js prettyprint-override"><code>#!/usr/bin/env wolframscript
  (* ::Package:: *)
  
  httpResponseTemplate[text_] := StringTemplate[
    &quot;HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Content-Type: text/plain;charset=ISO-8859-1
  Content-Length: `2`
  Date: Wed, 26 Jun 2013 07:00:56 GMT
  
  `1`&quot;
  ][text, StringLength[text]];
  
  listener = SocketListen[address,
      Module[{
        socket = #SourceSocket,
        message = #Data,
        func,
        query,
        result
      },
  (*      Print[message];*)
        query = StringExtract[message, &quot;\n&quot; -&gt; 1];
        func = StringCases[query, &quot;GET /&quot; ~~ f__ ~~ &quot; HTTP/1.1&quot; :&gt; f, 1][[1]];
        result = ToExpression[func][];
        BinaryWrite[socket,
          httpResponseTemplate[
            &quot;Hello, World!\nYou called the &quot; &lt;&gt; func &lt;&gt; &quot;\nResult is: &quot; &lt;&gt;
                ToString[result] &lt;&gt; &quot;\n&quot;
          ]
        ]
      ]&amp;
  ];
  
  
  While[True, Pause[60]]
  </code></pre>
  <p>I found that described Wolfram server has a peculiarity. The first argument of Wolfram function <code>SocketListen</code> can not contain hostname from docker-compose file as a host address. However, absence of the docker hostname leads to inaccessibility of the server from the outside the container.</p>
  <p>Need of the indication of the hostname can be proved by a netcat server, created inside the container. For example, the first variant below creates an accessible server, but the others — a server, inaccessible from the outside.</p>
  <pre class="lang-sh prettyprint-override"><code>echo -e &quot;HTTP/1.1 200 OK\n\n $(date)&quot; | nc -l wm 8000
  echo -e &quot;HTTP/1.1 200 OK\n\n $(date)&quot; | nc -l localhost 8000
  echo -e &quot;HTTP/1.1 200 OK\n\n $(date)&quot; | nc -l 127.0.0.1 8000
  </code></pre>
  <p>Variants for Wolfram, similar to the second and third ones, give the same result: inaccessibility from the outside. The <code>tcp_server.wls</code> file contains symbol <code>address</code>. It must be replaced with an exact string or integer before use. Here are Wolfram errors for all variants I've tried below.</p>
  <p><code>&quot;http://wm:8000&quot;</code> -&gt; <code>SocketOpen::addrspec: The host specification http://wm:8000 is wrong because the port number conflicts with the scheme specification</code></p>
  <p><code>&quot;http://localhost:8000&quot;</code> -&gt; <code>SocketOpen::addrspec: The host specification http://localhost:8000 is wrong because the port number conflicts with the scheme specification</code></p>
  <p><code>&quot;http://127.0.0.1:8000&quot;</code> -&gt; <code>SocketOpen::addrspec: The host specification http://127.0.0.1:8000 is wrong because the port number conflicts with the scheme specification</code></p>
  <p><code>&quot;wm:8000&quot;</code> -&gt; <code>SocketOpen::zmqexception: A ZeroMQ exception was thrown - No such device (code 19)</code></p>
  <p><code>&quot;localhost:8000&quot;</code> -&gt; <code>SocketOpen::zmqexception: A ZeroMQ exception was thrown - No such device (code 19)</code></p>
  <p><code>&quot;127.0.0.1:8000&quot;</code> -&gt; <code>without errors, but inaccessible from the outside (accessible only from inside)</code></p>
  <p><code>&quot;:8000&quot;</code> -&gt; <code>SocketOpen::addrspec: The host specification :8000 is wrong because it has an invalid domain specification</code></p>
  <p><code>8000</code> -&gt; <code>without errors, but inaccessible from the outside (accessible only from inside)</code></p>
  <p>The same was for other ports.</p>
  <p><strong>How can I force Wolfram to listen <code>http://wm:8000</code> or how to change docker settings in the sense of a substitution of an actual hostname by 127.0.0.1 while transfer it via docker network?</strong></p>
  <p>Before you build the Mathematica image, you need to change a licensing method inside the <code>Dockerfile</code> to the one you use (currently my network license is used) and download the linux installer <code>Mathematica_12.1.1_LINUX.sh</code> from Wolfram official site and put it into the folder with the three attachments from the beginning of this post.</p>
  <p>Note, that this is a draft of a project. The full one will contain other services inside <code>docker-compose.yml</code>, e.g. Go server, that shall be accessible from the outside too.</p>