Nextmv engines and apps are capable of being deployed to Docker containers. The following recipe demonstrates building and deploying our Knapsack engine into a Docker container using the HTTP runner. We make HTTP requests to it using curl
.
Files
This recipe can be built in any directory. We use knapsack-http
as the top level folder. We will create the following files.
Dockerfile
Create a Dockerfile
in the project root that contains the following code.
We use a "distroless" base Docker image. We set environment variables in the image to limit model runtime and to return only the last solution in the HTTP response.
More configuration options can be found in the Environment Variables and CLI Options section of our docs. The COPY
command copies the executable from our local machine to the Docker image. The ENTRYPOINT
configures our container as an executable that accepts input parameters.
main.go
Within the model's main.go
file import the HTTP runner and call it in the main()
function.
data/input-11items.json
We can use the same data file from the CLI runner recipe for testing this one.
Docker
Building a binary executable
To download and install the packages needed to build our binary we run the following commands at the root of the project.
First, we create a go.mod
file which defines the import path of the current Go module as well as other dependencies. This is done by running the command go mod init
on the root of the project. Next, run go get ./...
. You'll notice that a go.sum
file is created on the project's root. This contains a list of hashes associated to each package to ensure the same files are used for each build.
To build our executable we then run the following commands:
Here, we set environment variables so Go cross compiles the binary for a Linux operating system. The go build
command builds an executable from the model's main.go
file.
Building a Docker image
To build a Docker image, run the following command from the the root of the project.
docker build
constructs a Docker image based on the contents of our Dockerfile
. Note that the image is automatically tagged with latest
. If we want to version the image, we add a tag to the build command.
Running a Docker container
Once the setup is complete, from your terminal you can run the Docker container:
The --rm
flag cleans up the container after it finishes execution. -d
allows us to run our container in the background. To see error messages use docker logs. The -p
flag exposes port 8080 and binds it to port 5000 of the Docker container. Our container is now ready to receive requests.
In the terminal, the server response will include the model's solution.
Using a web server
We can also put a reverse proxy in front of our knapsack-http
using NGINX. This gives us useful web server features such as load balancing, request queues and caching.
Create a folder called knapsack/
, move the Dockerfile
, main.go
, go.mod
, go.sum
and the knapsack-http
binary to the knapsack/
folder. Then, create a separate folder at the same level as the knapsack/
folder called nginx/
. Inside the nginx/
folder create a Dockerfile
and an nginx.conf
file. In the NGINX Dockerfile
add the following:
This removes the existing configuration file (default.conf
) and replaces it with our own. Add the following to an nginx.conf
file. You may wish to replace the knapsack-http
placeholder with the name of your project:
Our NGINX reverse proxy will route requests from the container knapsack-http_nginx_1
to the container knapsack-http_knapsack_1
. Docker automatically aliases container names to their IP addresses. Finally, create a docker-compose.yml
file at the root of the project.
Your file structure should look like the following:
Now docker stop
the existing knapsack-http
and use Docker Compose to bring up both Hop and NGINX.
The -p
flag specifies the project name. If the -p
flag is not provided Docker will use the folder name instead. The -d
flag sets the container to run in "detached" mode. You can post the input file to the web server using the command:
If any changes to the nginx.conf
file or knapsack binary are made you will need to rebuild the Docker images. This can be done with docker-compose build
.