Deploy a ClamAV Docker container with AWS CDK on ECS

Marc Logemann
AWS Factory
Published in
4 min readJun 23, 2020

For an onPremise-to-cloud project, i was asked to port a java application to AWS. Before the migration the application talked to a ClamAV daemon on the same server so we needed a quick alternative to be hosted on AWS.

The application already sits inside a private subnet on a ECS cluster powered by an EC2 instance, so i thought that putting another another cluster, this time with Fargate might be a good choice. Since both are in the same VPC and even in the same subnet, communication is not the problem, nevertheless some things needed to be done, to have a nice running service.

As always i put the complete code on display and explain the different sections step-by-step. I will be using typescript for the CDK code because that’s the way i roll.

What you don’t see here.

This is not a complete CDK application but only one specific Stack i am creating. The ExtendedStackProps class is an extension of the StackProps class from the core package. I just added some properties like vpc and others which not relevant here. Since most of my stacks need my “base” VPC, i pass it to them with the help of ExtendedStackProps.

But what you see…

is a pretty straightforward ECS configuration. First we create an ECS cluster and pass it the mentioned VPC. The taskDefinition only contains the Fargate Task sizing. Before you start digging into the docs regarding the possible options, here they are:

I had problems giving the task less than 2 gig of ram resulting in weird shutdown and startups. But feel free to play with the values.

Because i really like having control over log group names, retention and removalPolicies, i normally create my log groups on my own. CDK creates ok-to-use defaults if you don’t supply anything but especially in the heavy development of your CDK project, you gonna hate all those created log-groups with weird names on each and every deploy.

Adding a container is straightforward too. We just supply the logging thing, define which docker image to use and do a port mapping, so that the daemon’s port is exposed to the outside world.

Exposing is not enough

You also need to have a security group on your ecsService which allows incoming traffic on 3010, the port where ClamAV is listening to. Again with regard to naming resources. I also like when SecurityGroups have sensible names. Apart from letting traffic on 3010 flow in, i also wanted to have ICMP go through. This is most likely useful in the early stages of your CDK project. I would remove that later when things stabilize.

Packaging it all together

The FargateService class does all the wiring and a bit more. Let’s start with the usual stuff you see in other blogs too. We pass the cluster reference, the taskDefintion and the securityGroup to the Fargate Service. Since i want control of where the task is placed, i also defined some networking essentials via vpcSubnets.

And then we have one attribute called cloudMapOptions in the ecsService definition and at the very top of the code, right inside the Cluster definition, we see a defaultCloudMapNamespace attribute. So what are these?

AWS Cloud Map

This is quite a powerful feature in AWS. How it exactly works would exceed the size of this blog but you can read all the details here: https://aws.amazon.com/cloud-map/?nc1=h_ls

But i give you a very short intro to it. In defaultCloudMapNamespace, you define some defaults for your cluster with regard to cloudmap. The name could be the domain name for your company or application. By supplying the VPC, all resources in that VPC can ask for the name of the service. But the servicename is not completely defined yet. This we do in one of the last lines of the code with the attribute name of cloudMapOptions.

The result of this configuration is a private Zone to be created on the domain “example.com”. In Route53 speak, the name is the subdomain part. At the end, we will get an A record called clamav.example.com in a private hosted Zone in Route53. The best part is, every resource deployed in the VPC can now ask for clamav.example.com and get the currently assigned IP address. You will like it especially in the CDK dev process where you tear down and recreate a Stack much more often.

The Result

So now, after deploying this stack, we have a running ClamAv installation listening on port 3010 for new requests. Clients like other applications inside the VPC can easily send requests to clamav.example.com:3010 and happily getting things virus scanned.

I hope you like this little receipt. Nothing fancy but always good to have one at your fingertips.

If you want to know more about well architected cloud applications on Amazon AWS or how to use Google Flutter with Firebase, feel free to head over to https://okaycloud.de for more infos.

--

--

Marc Logemann
AWS Factory

Entrepreneur & CTO - (AWS) Software Architect, likes Typescript, Java and Flutter, located in the Cloud, Berlin and Osnabrück.