### ----------------------------------------------------
### -- cro
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Worthington <jnthn@jnthn.net>
### -- File: docs/docker-deployment.md
### ----------------------------------------------------
# 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 http://0.0.0.0:10000
```

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 http://0.0.0.0:10000
```

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`**](https://hub.docker.com/r/croservices/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`**](https://hub.docker.com/r/croservices/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`**](https://hub.docker.com/r/croservices/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](https://hub.docker.com/r/croservices/cro/)
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.8.3

# Copy the application so it lives under /app
RUN mkdir /app
COPY . /app
WORKDIR /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 . && raku -c -Ilib service.raku

# Be sure to update the environment variable names to match those in the
# entrypoint script!
ENV MY_SERVICE_PORT="10000" MY_SERVICE_HOST="0.0.0.0"

# Expose the port above
EXPOSE 10000

# Run the service when the container is run
CMD raku -Ilib service.raku
```

Also consider having a `.dockerignore` file containing:

```
.precomp/
```

## Tips for deploying Cro services with Docker

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

* Always use a versioned base image; there is no `:latest` tag.
* 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.


