Docker containers aren't just for long running tasks
Tags: docker, devops, opensource, showdev
Published: 2019-05-27 12:03:59

Docker makes it easy to run long-running services like [sql server](https://hub.docker.com/_/microsoft-mssql-server) or [nzbget](https://hub.docker.com/r/linuxserver/nzbget/), but did you know that docker is also an excellent option for executing shorter workloads? This could be [compiling a dotnet core program](https://hub.docker.com/_/microsoft-dotnet-core) without installing the sdk, or [building your jekyll blog](https://hub.docker.com/r/jekyll/jekyll/) without installing ruby. 

To demonstrate both a short task use-case and the ease of creating your own docker containers, in this post I'll build a container that lets you, and me, push log files or any other text content at pastebin.com via the commandline.

## Publishing logs from any VM 

Pastebin lets you quickly post and share text files online.  They offer an [API](https://pastebin.com/api) so you can automate this process and have [examples of using it written in PHP](https://pastebin.com/api#2).  In my use-case, I need to publish logs created on transient VMs in Azure, but I don't want to install PHP or its dependencies, nor the scripts required to post the logs.  These VMs already have docker available, so my intention is to package Pastebin's PHP code into a container and push the container to docker hub.

This approach will let me use `docker run staff0rd/pastebin` on any VM, and the downloading and executing of the container will be taken care of automagically.

## Try it now

Now that I've built and published this container, you also have access to this functionality without having to go through any of the following effort.  If you've got docker installed, you can try this right now:

```bash
docker run -it staff0rd/pastebin -k <yourDevApiKey> "post this content to pastebin"
```

You can extend, modify, and use the source to create your own if you wish, or, [open a PR and collaborate](https://github.com/staff0rd/pastebin/pulls) on this one.  The [image is on dockerhub](https://hub.docker.com/r/staff0rd/pastebin) and the [source is on github](https://www.github.com/staff0rd/pastebin).

## Creating the Dockerfile

The [Dockerfile](https://github.com/staff0rd/pastebin/blob/master/Dockerfile) represents the image we're going to `docker build`, and is a great example of how trivial it is to create your own containers leveraging the hard work others have already done for you.  If I want to host or run a PHP script, I'm going to base my `Dockerfile` on the [official php image](https://hub.docker.com/_/php).  In this case, and as we'll see below, I ended up pulling in a php dependency manager, so I'll base my image on [that image](https://hub.docker.com/_/composer), which in turn is based on the php image.

```
FROM composer:1.8
COPY ./src /app
WORKDIR /app
RUN composer install
ENTRYPOINT [ "php", "./pastebin.php" ]
```

In the five lines above, I've set the base image for my container, copied my script and set the working directory, executed the install command for the dependency manager, and told the container to run the script when it starts.  I can run the following command and the container is ready to be used on the machine I built it.

```bash
docker build -t staff0rd/pastebin .
```

Then I can run this command, and the container can be `pull`ed or `run` from any machine on the internet:

```bash
docker push staff0rd/pastebin
```

## Building the script

The larger part of this exercise is building [the script that gets copied inside the container](https://github.com/staff0rd/pastebin/blob/master/src/pastebin.php).  For the actual execution I'll just use the [code exampled by pastebin](https://pastebin.com/api#2), but because this script will be encapsulated within the container, the parameters it needs are not obvious outside the container.  To solve this, I'll use [commando](https://github.com/nategood/commando) to build a nice CLI helper.  As a dependency, commando can be installed via [Composer](https://getcomposer.org/), a php dependency manager, and hence I based the Dockerfile on Composer rather than php directly.

At the very least, commando gives me a nice `--help` output, so the options implemented by the script within container are no longer a secret:

```bash
λ docker run -it staff0rd/pastebin --help

Examples:

docker run -it staff0rd/pastebin -k <devKey> "paste this text to pastebin!"
    Paste the given text to pastebin

cat myfile.log | docker run -i staff0rd/pastebin -k <devKey>
    Paste the contents of myfile.log to pastebin

docker run -it staff0rd/pastebin -k <devKey> -u <userName> --password <password>
    Retrieve a userKey to use associate pastes with your user

arg 0
     Content to to paste

-k/--devkey <argument>
     Required. Your api developer key

--help
     Show the help page for this command.

-j/--userkey <argument>
     Your user key

-n/--name <argument>
     Name or title of your paste

-p/--public
     Make this paste public.  Default is unlisted.

--password <argument>
     Your pastebin password

-u/--username <argument>
     Your pastebin user name
```

## Wrapping it up

I've pushed the [image](https://hub.docker.com/r/staff0rd/pastebin) to docker hub and enabled automatic builds, so any updates to the [git repo](https://github.com/staff0rd/pastebin) will result in a new image being built on docker hub.

Otherwise, I can (and so can you, because docker) send any file to pastebin on any docker-enabled host with the following: 

```bash
cat sendThisFile.txt | docker run -i staff0rd/pastebin -k thisIsMyDevKey
```

I hope this post has illustrated both how easy it is to create your own docker containers, and, how docker is also a great tool for both executing and distributing/deploying short-running tasks.