Deploying Cro services in Docker containers

To aid deployment of Cro services using Docker, a number of base images are provided. These all include a recent MoarVM and Rakudo release, which Cro has been tested on. The zef installer is also included, to aid installation of further dependencies during the container build. The images are Debian-based, making it easy to install packages with apt.

Generation with cro stub§

A Dockerfile is generated automatically when stubbing a service using the cro stub command. The Dockerfile will use a base image tied to the Cro version that you had installed when running cro-stub.

Using the image looks something like:

$ docker build -t my-service .
...lots of Docker output...
$ docker run --rm -p 10000:10000 my-service
Listening at

The service exposes itself and runs on port 10000 inside the container; to expose it as a different port on the host use something like:

$ docker run --rm -p 20000:10000 my-service
Listening at

Which makes it accessible as port 20000 on the host. Cro does not attempt to maintain or update this Docker file, so feel free to change it according to your needs.

Base images§

The following base images are available for application deployment:

  • **cro-core** - includes the Cro::Core distribution; ideal when no other base image is applicable, but at least saves installing the Cro::Core library.

  • **cro-http** - includes the Cro::HTTP distribution, which in turn depends on Cro::TLS and Cro::Core. Includes libraries required for TLS to work. Ideal for web services.

  • **cro-http-websocket** - as for cro-core-http, but also includes the Cro::WebSocket distribution. Ideal for web servies that also use web sockets.

There is also a cro base image which includes the development tools. This is not a good choice for deployment, since it includes a lot of modules that are only depended on by the cro command line tool. However, it may be convenient for trying out Cro without needing a local install.

Sample Dockerfile§

This is an annotated example of what would be generated by cro stub. If you created your service without that tool, then you can take some inspiration from this example to write a Dockerfile.

# Depend on the cro-http-websocket base image; pick a version
FROM croservices/cro-http-websocket:0.7.3

# Copy the application so it lives under /app
RUN mkdir /app
COPY . /app

# Install additional dependencies from META6.json. Then do a syntax check on
# the entrypoint. This in turn loads and pre-compiles the application, making
# sure any compilation errors will make the container build fail, and allowing
# for faster container startup.
RUN zef install --deps-only . && perl6 -c -Ilib service.p6

# Be sure to update the environment variable names to match those in the
# entrypoint script!

# Expose the port above
EXPOSE 10000

# Run the service when the container is run
CMD perl6 -Ilib service.p6

Also consider having a .dockerignore file containing:


Tips for deploying Cro services with Docker§

These aren't specific to Cro, but are worth a mention.

  • Always use a versioned base image rather than :latest

  • Make sure logging has been added to services, and preferably set up some kind of log aggregation. Unless you have an arrangement in place to send logs to a centralized logging solution, prefer logging to STDOUT/STDERR, as then the logs can be introspected by docker log, kubectl log, etc.

  • Prefer using a tool like Kubernetes rather than managing containers and configuration by hand

Docker containers can be deployed on various cloud providers, some of which provide hosted Kubernetes.