ImageMagick is an age-old tool (27 years old today!) for Linux which is used for image manipulation and generation. There's not much you cannot do with it, but one of the most common use-cases I've seen is reducing image size to generate thumbnails. In this blog post I want to give you a fresh take on ImageMagick and deploy it as a scaleable serverless function with OpenFaaS and Kubernetes, or Docker Swarm.
OpenFaaS is Serverless, but on your terms. Build serverless functions using Docker containers and deploy onto Kubernetes and Docker Swarm. Star or fork the repo here.
Pre-reqs
Follow the guide for setting up OpenFaaS Docker Swarm or Kubernetes below. If you already have a cluster ready or Docker on your laptop then this takes less than 60 seconds to deploy.
- Docker Swarm - easiest on a laptop
- Kubernetes
Once you've deployed OpenFaaS, we now need to install the FaaS CLI tool:
If you're on Linux or Windows type in:
$ curl -sL cli.openfaas.com | sudo -E sh
On Mac you can type in brew install faas-cli
Check it worked with faas-cli version
Deploy the samples
Clone the CLI from GitHub which contains several samples, including ImageMagick:
$ git clone https://github.com/alexellis/faas-cli
Now let's deploy the shrink-image function:
$ faas-cli deploy -f samples.yml --filter=shrink-image
Deploying: shrink-image.
...
shrink-image
will reduce any image to 50% of its size.
Test it out
The ImageMagick sample is deployed as shrink-image
. Let's grab a photo from Pexels who provide royalty-free images and then try it out:
$ curl -sSL "https://images.pexels.com/photos/464376/pexels-photo-464376.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb" > whale.jpg
If you checkout the image, you'll see it's around 1148 × 750 and 131KB in size.
Now let's shrink it to 50%:
$ cat whale.jpg | faas-cli invoke shrink-image > whale-small.jpg
If your server is remote, you can also pass the
--gateway
flag.
So now we can see the resulting image at 50% of the size - 817 × 500 and 115KB on disk.
How does it work?
Well for every request that comes into the function we fork ImageMagick, feed in the bytes of the larger image via STDIN and then read the response over STDOUT and send that back to the caller. The fwatchdog (fork watchdog) binary is placed into a container as the entrypoint and is responsible for enforcing timeouts and reading/writing values to and from your function via pipes.
sample/imagemagick/Dockerfile
FROM alpine:3.6
ADD https://github.com/alexellis/faas/releases/download/0.5.8-alpha/fwatchdog > /usr/bin/fwatchdog
RUN chmod +x /usr/bin/fwatchdog
# Alternatively use ADD https:// (which will not be cached by Docker builder)
RUN apk --no-cache add imagemagick
ENV fprocess="convert - -resize 50% fd:1"
Read more about the function watchdog here.
How do you do something different?
Edit the fprocess
variable in sample/imagemagick/Dockerfile and put 200% instead of 50% - and you can now scale-up thumbnails to double their original size.
Edit the samples.yml file and pick a new Docker image name and function name for your function:
upscale-image:
lang: Dockerfile
handler: ./sample/imagemagick
image: functions/upscaler
fprocess: "convert - -resize 200% fd:1"
Now we must re-build and re-deploy the functions:
$ faas-cli build --filter=upscale-image -f samples.yml
$ faas-cli deploy --filter=upscale-image -f samples.yml
You can now invoke it again:
$ cat whale.jpg | faas-cli invoke upscale-image > whale-bigger.jpg
As expected - the resulting size is 2296 × 1500 and 537KB.
What else can I do with ImageMagick?
Checkout the ImageMagick homepage here. Any ImageMagick commands can be pasted into the "fprocess" variable and re-built to make an image-processing pipeline that can scale as a Serverless function in your cluster.
Here's an example of a function which can print text (you supply) on top of an image:
faas-and-furious/faas-contributor-stamp
Here's an example of what you can do once the function is deployed:
$ curl http://localhost:8080/function/faas-stamp --data-binary @whale-small.jpg > whale-text.jpg
You can even customise the text by passing an addition HTTP header like this:
$ curl http://localhost:8080/function/faas-stamp -H "X-Caption: I'm running Serverless on my own terms" --data-binary @whale-small.jpg > whale-text.jpg
Task: Make polaroids
If you fancy a challenge - why not try editing the function to apply a "Polaroid" style to your pictures?
More about OpenFaaS
OpenFaaS is serverless on your terms. There is no need to worry about being locked-in to a complicated architecture, set of tools or a particular cloud vendor.
Find out more about our project by heading over to openfaas.com and be sure to Star the project on GitHub to show your support.
OpenFaaS is cloud native and has Prometheus metrics built-in - so you can run it on any hardware and at scale. Pick private, public, hybrid-cloud or even a Raspberry Pi cluster.
Sit back with a coffee and learn about our CLI
Find out what Serverless is, what the use-cases are and who's using OpenFaaS: