An application in Docker is not of much use if it cannot communicate with the outside world. A typical Docker application consists of a collection of containers, each designed to carry out a specific function, and which can communicate with each other and the outside world through the HTTP protocol. Exchanging data with Matlab docker containers is not possible with standard Matlab nor with the docker tools available since Matlab 2020b. However the Modelit Webserver toolbox makes it possible to execute Matlab code in a Docker container as a microservice.
In this post we show how to run a compiled Matlab application in a Docker container that is able to send and receive messages from other services. This post is a continuation of the Matlab in Docker post in which a Docker container was created in which a simple "Hello world" Matlab function was executed.
Prerequisites for this example are:
- Matlab and the Matlab Compiler for Unix
- Modelit Webserver toolbox
- Docker
The next steps describe how existing Matlab code can be geconverted to a Matlab webservice that can be executed in a Docker container.
Assume that there exists an existing Matlab algorithm with signature given in Code fragment 8
function output = algorithm(input)
Code fragment 8: Signature of an existing Matlab algorithm that needs to be converted to work in a Docker container.
An existing Matlab algorithm can be converted to a Matlab webservice by implementing the following steps. See Code fragment 9 for the corresponding Matlab code:
- Create a modelit.web.server.Server object that can receive HTTP requests on a specified port.
- Define the callback to be executed when an HTTP request arrives.
- Start the server and stay in a eternal loop to make sure the service stays active.
- Get the data from the (modelit.web.server.HttpExchange) event.
- Convert the data (e.g. JSON or XML) to a Matlab variable.
- Generate the response by executing the original algorithm.
- Convert the response to JSON or XML
- Set the HTTP headers (e.g. Content-Type).
- Send the response and the HTTP statuscode to the client.
function callback(event) % The first argument contains the data from the HTTP request input = event.getBody(); % Convert these data so it can be used in Matlab input = jsondecode(input); % Call the original algorithm with this input output = algorithm(input) % Convert the output to json so it can be handled by the service which sent the request output = jsonencode(output); % Set the MIME type to json. event.addResponseHeader('Content-Type', 'application/json'); % Return the generated output, set HTTP Statuscode 200: OK event.send(200, response);it(request);
This code can be compiled with the following command:Code fragment 9: An existing algorithm that can be executed with an HTTP request.
>> mcc -m -d sh_microservice microservice |
Code fragment 2: Command to compile Matlab code in the file microservice.m
Executing the mcc command in Code fragment 2 produces two files in the directory sh_microservice:
- microservice
the compiled microservice.m - run_microservice.sh
a shell script to execute the application
Using the shell command in Code fragment 3 the hello application in the sh_hello directory can be executed.
> ./run_microservice.sh |
Code fragment 3: Command to execute the application.
Now the application must be packed in a Docker container. This packing consists of the configuration of a Dockerfile: a file that contains all the instructions to build a Docker image. An image typically consists of the operating system, utilities and all dependencies needed to run the application. Docker uses this image to automatically generate a container in which the application can be executed.
Code fragment 4 contains the Dockerfile to generate a Docker image with the Matlab application.
FROM alpine:latest
LABEL Description="Matlab 2019b microservice"
COPY run_hello.sh . COPY hello .
RUN apt-get update RUN apt-get install -y libxt-dev RUN chmod a+x /run_microservice.sh RUN chmod a+x /microservice
CMD ["./run_microservice.sh", "/opt/mcr/v97"] |
Code fragment 4: Dockerfile for the execution of a compiled Matlab R2019b application in a Docker container.
This Dockerfile consists of the following parts:
- The first line with the command FROM specifies which image is used as base for this image. This is often the desired operating system, for example: alpine, ubuntu or debian, seeDocker Hub.
- Add metadata with the command LABEL. For example the version or information about the maintainer.
- Using the COPY and RUN commands to copy required files to the image and execute shell commands, for example to set permissions. The command “apt-get install -y libxt-dev” copies a library in the image that is necessary for Matlab.
- ENV: Define environment variables with this command, these variable can be used in the call to the Matlab shell script.
- CMD: The command to execute to run the compiled Matlab application followed by the input arguments, in this case the path to the MCR for Matlab 2019b.
The Dockerfile can be used to build a container with the instruction in Code fragment 5. This command generates a container with the tag hello based on the Dockerfile in the current directory (indicated with the “.”)
> docker build --tag microservice . |
Code fragment 5: Command to build a Docker image.
The generated image can be used to build and run a container:
> docker run microservice |
Code fragment 6: Command to execute a Docker container with tag microservice.
Use the command in Code fragment 7 to get an overview of the available functions for Docker containers and docker images.
> docker image --help > docker container --help |
Code fragment 7: Get help for Docker image and container methods.