Deploy your own production-ready Jenkins in AWS ECS

Deploying Jenkins to AWS ECS

Last Updated on March 18, 2021

Deploying a continuous integration service such as Jenkins is an important step when kicking off your development project. In this article you’ll discover how to deploy Jenkins into the AWS Elastic Container Service (ECS), meaning you’ll have your own highly available Jenkins instance available to you over the internet.

We’ll be following all the best practices to get Jenkins production-ready, including making sure:

  • Jenkins is always available to you even if an entire AWS availability zone goes down
  • all Jenkins data is stored on a persistent volume
  • Jenkins runs inside a private network with strict security controls to ensure nobody except authenticated users have access
  • any changes to the infrastructure can be made easily via AWS CloudFormation templates

This wish list is not difficult to achieve when using services from a cloud provider such as AWS. First though. let’s get an understanding of how Jenkins works before figuring out how to deploy it to AWS.

This is the first article in this three-part series about deploying Jenkins into AWS. Here are details of all three articles:

  • in Part 1 Deploy your own production-ready Jenkins in AWS ECS (this article) we’ll explore how to setup a robust Jenkins master in AWS using CloudFormation
  • in Part 2 Running Jenkins jobs in AWS ECS with slave agents we’ll get slave jobs running in ECS through a full worked example, doing all the cloud configuration manually for a full understanding of the process
  • in Part 3 Using Jenkins Configuration as Code to setup AWS slave agents we’ll improve what we had in part 2 by setting up our Jenkins master’s cloud configuration automatically using Jenkins Configuration as Code

Jenkins architecture overview

This diagram describes a common Jenkins use case, where we need to run jobs that build software whose code is checked out of a version control system such as Git.

Jenkins is designed to run a single master node responsible for serving the web UI, handling configuration, running jobs, and managing interactions with slave nodes. Jenkins slave nodes also run jobs, and they allow for horizontal scalability since you can have many resource intensive jobs running at the same time without affecting the master node.

Also bear in mind that:

  • Jenkins stores it’s configuration and data (workspaces, job history etc.) on a filesystem accessed from the master node
  • because of this, only a single master node can run at the same time otherwise there is risk of data corruption
  • using a single master node without slaves is fine for light Jenkins usage

To keep things focused, for this article we’ll aim to deploy a single master node for running jobs. Executing jobs on slave nodes will be covered in a follow-up article.

Why would you deploy Jenkins into ECS?

AWS ECS is a container orchestration framework much like it’s better-known more fashionable cousin Kubernetes. ECS provides everything you need to deploy services as Docker containers, including handing scaling, failover, networking, and security.

The other nice things about ECS are:

  • it’s fairly straightforward to get up and running quickly, especially if you use a templating language like CloudFormation or Terraform
  • it integrates very well with other AWS technologies such as Application Load Balancers, Security Groups, and EC2

If you know that AWS is the cloud provider you want to use in the long-term, then for getting a service such as Jenkins deployed ECS is an ideal choice. 👍

AWS & ECS lingo 📚

AWS has a lot of magical acronyms and terms that can sometimes send your head in a spin. Let’s get the relevant ones out in the open before continuing.

  • ECS Task – a unit of execution within ECS which equates to a Docker container running a single instance of an application
  • ECS Service – an orchestration layer, one for each type of application you want to deploy (e.g. Jenkins). It manages the ECS tasks for you, making sure the desired number are running, and handles security and networking.
  • ECS Cluster – a grouping of ECS tasks and services. A cluster can have a group of EC2 instances assigned to it on which it deploys tasks. This is called the EC2 launch type. Another launch type is Fargate, where AWS takes care of provisioning resources on which tasks run. Since you don’t have to provision any EC2 instances yourself, it makes setup a lot simpler. We’ll be using the Fargate launch type in this article.
  • AWS Region – a geographical area into which you deploy AWS resources, e.g. eu-west-1 (Ireland), eu-west-2 (London). We’ll be using eu-west-1 in this article.
  • AWS Availability Zone – isolated datacentres within an AWS Region. Each region has multiple availability zones e.g. eu-west-1 has eu-west-1a, eu-west-1b, and eu-west-1c.

A Jenkins solution in ECS

OK, so we’ve given ECS the thumbs up, but let’s think about what specific features we can use for our Jenkins deployment given the constraints of the Jenkins architecture described earlier. The following points are marked on the diagram below, ‘cos I’m nice like that.

1 Integration with Application Load Balancer (ALB) – the only access point into Jenkins should be via an ALB which serves the Jenkins UI over HTTPS on port 443. An SSL certificate will be provided to the ALB for the domain we want Jenkins to be available on. Registration of ECS tasks into the ALB is handled automatically by ECS.
2 Integration with Security Groups – the Jenkins ECS service should be assigned a security group that only allows access on the Jenkins port (8080) from the ALB. We’ll provide full outbound internet access to Jenkins in order that updates and plugins can be installed.
3 Persistent storage – AWS now offers tight integration between ECS tasks and the Elastic File System (EFS) service, meaning our Jenkins data will be safe if the container gets stopped for any reason.
4 Failover – because our Jenkins instance runs as a single master we can’t run multiple instances of it, so it will be deployed into a single availability zone. Although problems with an AWS availability zone are rare, we can provide redundancy by creating an ECS service which spans multiple availability zones. This way, Jenkins will automatically recover if the availability zone it’s running on fails.


Traditionally the Elastic Block Store (EBS) is the storage type to use when attaching a volume to an EC2 instance. This won’t work for our use case, because:

  • we’re running in ECS Fargate, which doesn’t support EBS
  • an EBS volume can only exist in a single availability zone, making things difficult for our high availability requirement

Fortunately though, the Elastic File System (EFS) can run in Fargate (as of April 2020) and its volumes can exist in multiple availability zones, which is why it’s our choice for this article.

Attaching EFS to Fargate containers: 1,000 foot view

To keep this article on-point, I’ll explain just enough information about attaching EFS to Fargate so that you can understand the main concepts. Sound fair?

EFS is an Network File System (NFS) type file system. It can be attached to one or many devices at the same time, each of which can read and write data. In the case of Fargate, you can attach an EFS file system to multiple ECS tasks.

The way this works with Fargate is using another resource that you have to create called a mount target. A mount target has its own network interface and therefore IP address, and it’s via the mount target that an EFS resource is attached to a Fargate container.

You can see from the diagram above that each availability zone has its own mount target. EFS itself stores data across multiple availability zones. This means that if an availability zone fails, whatever Fargate containers are in the other availability zone keep running uninterrupted via the corresponding mount target.

As already mentioned we’ll only have one Jenkins master running at once. But, these EFS features are very helpful to ensure Jenkins can come back automatically with the same data should an availability zone fail.

Deploying Jenkins into ECS with CloudFormation

Let’s get this show on the road by deploying all the AWS resources required to implement the solution above, using the AWS templating engine CloudFormation.

I recommend first reading through the descriptions that follow so you know what AWS resources you’re deploying. But, if you’re a super-keen eager beaver, jump right in by hitting Launch Stack below. This will create the CloudFormation stack in your own AWS account, resulting in a running Jenkins instance deployed in a new VPC and ECS cluster, available over the internet.

Full details of what to do when you click the Launch Stack button are given in the section Launching the CloudFormation stack in your AWS account.

Launch CloudFormation stack

First though, let’s run through the two template files that make up this infrastructure deployment.

Stack one: VPC and networking

This nested stack (default-vpc.yml) contains all the resources to create a standard VPC setup:

  • VPC – a new network in the AWS cloud, where we’ll be deploying all resources. Note that for us to attach an EFS volume to a Fargate container in this VPC, it must have DNS hostnames enabled.
  • public subnets x 2 (in different availability zones) – here we’ll deploy our ALB, so it’s accessible to the internet
  • private subnets x 2 (in different availability zones) – here we’ll deploy our Jenkins service, so it’s not directly accessible to the internet
  • an internet gateway – attached to the public subnets, this is the network’s route to the internet
  • NAT gateway x 2 – these allow traffic from any services deployed in the private subnets to reach the internet via the internet gateway
  • route tables, elastic IP, etc. – see the CloudFormation template for full details of miscellaneous resources

To learn more about these AWS resources, see my guide VPCs, subnets, and gateways – fundamentals for working with containers in AWS.

Nested stacks

A nested stack is a reusable CloudFormation template. Because we’re using a standard setup for the VPC/networking this has been extracted out into a separate nested stack, which can also be reused in future articles.

Stack two: ECS cluster, Jenkins ECS task, & ECS service

This main stack (jenkins-for-ecs.yml) references the nested stack created above, then it defines all the ECS resources required to get a Jenkins ECS service running, and hooks it into a load balancer.

ECS cluster

Our ECS cluster will be given the name default-cluster. Imaginative, I know!

    Type: AWS::ECS::Cluster
      ClusterName: default-cluster
ECS task definition

The Jenkins ECS task definition references the official Jenkins Docker image, and configures:

  • PortMappings provides access to the container on port 8080
  • MountPoints defines a mount point for a volume called jenkins-home inside the container at /var/jenkins_home (where Jenkins writes its data)
  • the LogConfiguration sets up logging to CloudWatch using the CloudwatchLogsGroup resource, which keeps logs for 14 days
  • the Volumes section contains a jenkins-home volume which uses the EFSVolumeConfiguration type to reference an EFS volume defined later on. Note that TransitEncryption is set to ENABLED so that Jenkins storage data is encrypted as it passes between the ECS task and EFS.
    Type: AWS::ECS::TaskDefinition
      Family: !Sub jenkins-task
      Cpu: 512
      Memory: 1024
      NetworkMode: awsvpc
      TaskRoleArn: !Ref JenkinsRole
      ExecutionRoleArn: !Ref JenkinsExecutionRole
        - FARGATE
        - EC2
        - Name: jenkins
          Image: jenkins/jenkins:lts
            - ContainerPort: 8080
            - SourceVolume: jenkins-home
              ContainerPath: /var/jenkins_home
            LogDriver: awslogs
              awslogs-group: !Ref CloudwatchLogsGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: jenkins
        - Name: jenkins-home
            FilesystemId: !Ref FileSystemResource
            TransitEncryption: ENABLED
              AccessPointId: !Ref AccessPointResource
              IAM: ENABLED
    Type: AWS::Logs::LogGroup
      LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]
      RetentionInDays: 14
ECS service

The Jenkins ECS service will be responsible for making sure the task (i.e. the container) is running, and it also manages networking:

  • the DesiredCount of 1 means we’ll get a single Jenkins instance
  • the LaunchType of FARGATE means that AWS will be provisioning any underlying resources for us
  • the PlatformVersion must be 1.4.0 otherwise the functionality to mount EFS volumes inside our Fargate container won’t work
  • the DeploymentConfiguration controls how ECS handles deployments when tasks need to be recreated. In our case we want at most one Jenkins instance to be running at once
  • the provided NetworkConfiguration means the service can create ECS tasks in any of the given subnets. It also says the tasks should have network access restricted as described in the JenkinsSecurityGroup, which gives inbound access from the ALB on port 8080 (see template for details).
  • the LoadBalancers section says the service should automatically register itself with the provided target group, defined in the next section
    Type: AWS::ECS::Service
    DependsOn: LoadBalancerListener
      Cluster: !Ref ECSCluster
      TaskDefinition: !Ref JenkinsTaskDefinition
      DesiredCount: 1
      HealthCheckGracePeriodSeconds: 300
      LaunchType: FARGATE
      PlatformVersion: 1.4.0
        MinimumHealthyPercent: 0
        MaximumPercent: 100
          AssignPublicIp: ENABLED
            - !GetAtt VPCStack.Outputs.PrivateSubnet1
            - !GetAtt VPCStack.Outputs.PrivateSubnet2
            - !GetAtt JenkinsSecurityGroup.GroupId
        - ContainerName: jenkins
          ContainerPort: 8080
          TargetGroupArn: !Ref JenkinsTargetGroup
Load balancer and related resources

To expose Jenkins to the internet over SSL we’ll create a load balancer and a load balancer listener to receive incoming HTTPS traffic.

  • the LoadBalancer spans two public subnets
  • it’s assigned a LoadBalancerSecurityGroup which allows inbound traffic from the internet on the SSL port 443, and outbound traffic to our Jenkins instance only
  • the LoadBalancerListener:
    • listens for HTTPS traffic on port 443
    • is assigned a certificate id which must be passed into the CloudFormation template as a parameter (see Certificate & DNS setup below)
    • by default forwards traffic to the Jenkins target group
  • the JenkinsTargetGroup is where the ECS service will register the Jenkins task IP address
    • the HealthCheckpath is /login which returns a 200
    • the Protocol at this point is HTTP since by this point traffic has been decrypted by the ALB
    • deregistration_delay is how long the target group will wait for requests to drain from a target when it’s being deregistered. Reducing this from the default of 5 minutes to 10 seconds means that changes to the Jenkins task will happen quicker.
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
        - !GetAtt VPCStack.Outputs.PublicSubnet1
        - !GetAtt VPCStack.Outputs.PublicSubnet2
        - !Ref LoadBalancerSecurityGroup
    Type: AWS::EC2::SecurityGroup
      GroupName: LoadBalancerSecurityGroup
      GroupDescription: Security group for load balancer
      VpcId: !GetAtt VPCStack.Outputs.VPC
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
        - IpProtocol: tcp
          FromPort: 8080
          ToPort: 8080
          DestinationSecurityGroupId: !Ref JenkinsSecurityGroup
    Type: AWS::ElasticLoadBalancingV2::Listener
        - CertificateArn: !Ref CertificateArn
        - Type: forward
              - TargetGroupArn: !Ref JenkinsTargetGroup
      LoadBalancerArn: !Ref LoadBalancer
      Port: 443
      Protocol: HTTPS
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
      HealthCheckPath: /login
      Name: JenkinsTargetGroup
      Port: 8080
      Protocol: HTTP
      TargetType: ip
      VpcId: !GetAtt VPCStack.Outputs.VPC
        - Key: deregistration_delay.timeout_seconds
          Value: 10

Certificate & DNS setup

You can use an existing certificate or create one through Services > Certificate Manager. Create the certificate for whatever domain you want Jenkins to be available on. In my case I wanted to serve Jenkins on so created a wildcard certificate for *

Once your domain has been validated and the certificate has been created, the certificate ARN should be passed as a parameter when launching the CloudFormation stack (see Launching the CloudFormation stack in your AWS account below).

After the stack has been created, on the stack details page select the Outputs tab and copy the value from LoadBalancerDNSName. This is the DNS name of the load balancer created by CloudFormation.

Jenkins stack outputs

Then add the copied value into your DNS through whatever tool you use (AWS or otherwise) as a CNAME record.

EFS File System
  • the EFSSecurityGroup provides access from the Jenkins security group on port 2049, the default EFS port
  • the FileSystemResource is the volume itself, which we provide a name of jenkins-home
  • Encrypted is set to true to enable encryption at rest
  • two mount targets MountTargetResource1 and MountTargetResource2 provide access from ECS tasks to the file system. We create a mount target in each of our private subnets, so depending on which availability zone our Jenkins ECS task gets placed, it will always have access to the file system.
    Type: AWS::EC2::SecurityGroup
      VpcId: !GetAtt VPCStack.Outputs.VPC
      GroupDescription: Enable EFS access via port 2049
        - IpProtocol: tcp
          FromPort: 2049
          ToPort: 2049
          SourceSecurityGroupId: !Ref JenkinsSecurityGroup
    Type: AWS::EFS::FileSystem
      Encrypted: true
        - Key: Name
          Value: jenkins-home
    Type: AWS::EFS::MountTarget
      FileSystemId: !Ref FileSystemResource
      SubnetId: !GetAtt VPCStack.Outputs.PrivateSubnet1
        - !GetAtt EFSSecurityGroup.GroupId
    Type: AWS::EFS::MountTarget
      FileSystemId: !Ref FileSystemResource
      SubnetId: !GetAtt VPCStack.Outputs.PrivateSubnet2
        - !GetAtt EFSSecurityGroup.GroupId
    Type: AWS::EFS::AccessPoint
      FileSystemId: !Ref FileSystemResource
        Uid: '1000'
        Gid: '1000'
          OwnerGid: '1000'
          OwnerUid: '1000'
          Permissions: '755'
        Path: '/jenkins-home'

Launching the CloudFormation stack in your AWS account

Now you know what resources are created in the CloudFormation templates you can go ahead and deploy the example using the Launch Stack button below:

Launch CloudFormation stack

When you click this button you’ll be taken to the Quick create stack page in your own AWS account.

  • provide a CertificateArn. This is the ARN of the certificate you want to attach to your ALB for HTTPS access (see the Certificates & DNS setup section for more details).
  • accept that this stack may create IAM resources and needs the CAPABILITY_AUTO_EXPAND capability

Click Create stack.

AWS will now go off and do its business, the infrastructure type business that is.

Go to Services > CloudFormation and you’ll see your CloudFormation stacks in the process of being created. After about 5 minutes all the stacks should be in the UPDATE_COMPLETE state.

Prod ready? Yes, but…

The CloudFormation I’ve supplied here deploys an example of a production ready Jenkins service into a new VPC. In applying this to your own production infrastructure, I suggest:

  1. making a copy of any CloudFormation templates provided here and hosting them in your own S3 bucket
  2. adjusting as necessary to integrate with your own VPC and subnets
  3. setting up log retention and automated EFS backups based on your own requirements
  4. limiting access to your Jenkins instance by IP if you can. This can be achieved by updating the LoadBalancerSecurityGroup ingress rule.

Getting started with the Jenkins instance

If you’ve applied the CloudFormation stack described above you’ll now have a shiny new Jenkins instance running. Be patient as even when the stack has applied Jenkins still takes a couple of minutes to start up. ⏰

You can access Jenkins using the ALB DNS name described in the Certificates & DNS setup section above, although you’ll have to accept the “Your connection is not private” warning about an insecure certificate. If you’ve setup your certificate and DNS correctly though, you’ll be able to access Jenkins with a valid certificate for the domain, which will look like this:

Grab the admin password by navigating to the ECS Task and clicking on the Logs tab. The password will be printed in the logs the first time Jenkins starts up. Look for the log line “Please use the following password to proceed to installation”.

Copy the password, paste it into Jenkins, and you’ll be off and away with the Jenkins setup wizard:

Once you’ve followed this through, you’ll have a Jenkins instance ready to start running some jobs!

Disaster recovery scenarios

Since the intention of this article is to create a production-ready Jenkins deployment, let’s put our money where our mouth is and test some disaster recovery scenarios.

1. ECS task failure

Scenario: the Jenkins ECS Task gets stopped for some reason

Requirement: the ECS task should restart automatically restoring service quickly

Test: go to the list of tasks in the cluster, select the Jenkins task, then click Stop

Observation: ECS restarts the task and Jenkins is available again in 2m00s. ✅

2. Availability zone failure

This is a real “squeaky bum time” scenario where an entire AWS availability zone datacentre goes down.

You can identify which availability zone your ECS task is running in by going to the task details page and clicking on the ENI Id under Network:

This opens up details of the Elastic Network Interface (ENI) which our ECS task uses to connect to the network and internet. Under Zone it tells us which availability zone this ENI and associated ECS task are in.

In my case I know then that I need to simulate a failure of eu-west-1a.

Sadly AWS won’t be very helpful in bringing down a whole availability zone for our testing. 😢 But, the next best thing we can do is to modify our Jenkins ECS service to force it to deploy into a different subnet and therefore a different availability zone.

In the main CloudFormation template jenkins-for-ecs.yml it passes a list of subnet ids through in the NetworkConfiguration section of the JenkinsService resource:

          AssignPublicIp: ENABLED
            - !GetAtt VPCStack.Outputs.PrivateSubnet1
            - !GetAtt VPCStack.Outputs.PrivateSubnet2
            - !GetAtt JenkinsSecurityGroup.GroupId

All we need to do is tweak this list so that it only contains PrivateSubnet2, which lives in the second availability zone in your region (in my case eu-west-1b).

          AssignPublicIp: ENABLED
            - !GetAtt VPCStack.Outputs.PrivateSubnet2
            - !GetAtt JenkinsSecurityGroup.GroupId

Once this change is applied the ECS service creates the ECS task in the remaining subnet, and the Jenkins instance is available again in 2m28s. ✅

Making these changes yourself

Download the original jenkins-for-ecs.yml template and make the above code change. To apply it, go to Services > CloudFormation, then select the stack and click Update. You can then select Replace current template and upload the file. Keep clicking Next then on the final screen click to say you accept the additional capabilities, then click Update stack.

Next steps

Even though now you have created a production-ready Jenkins instance which is secure and highly available, there’s still some way to go before you have a full continuous integration solution in place. Check out the next article in this series Running Jenkins jobs in AWS ECS with slave agents where we’ll learn how to horizontally scale Jenkins workloads by running jobs on slave agents.

As a final point, if you followed the example in this tutorial don’t forget to delete the CloudFormation stack once you’re finished with it, to avoid incurring unnecessary charges.

Discover more Jenkins CloudFormation templates

Liked the example from this article?
Check out my premium one-click Jenkins CloudFormation templates covering many different use cases.

✅ Run Jenkins securely in your own AWS account
✅ Try out different scenarios for running Jenkins in AWS
✅ Take the bits you like and incorporate them into your own templates

Want to learn more about Jenkins?
Check out the full selection of Jenkins tutorials.



The CloudFormation stack can be applied directly to your AWS account by clicking below:

Launch CloudFormation stack

There were two templates used in this article:

  1. jenkins-for-ecs.yml (main template)
  2. default-vpc.yml (nested)

The Docker image used in this article was jenkins/jenkins, available on Docker Hub


Check out the accompanying video over on my YouTube channel

Want to learn more about Jenkins?
Check out the full selection of Jenkins tutorials.

Deploy your own production-ready Jenkins in AWS ECS

28 thoughts on “Deploy your own production-ready Jenkins in AWS ECS

  1. Hi Tom, thanks a lot for this guide.
    I got stuck on the second screen, for plugin installations, and I don’t see any errors in the logs.
    I stumbled on this old open bug:, but seeing all the comments above, it seems that most people do manage to pass this phase.
    Any ideas?
    Thanks again,

    1. Hi Erez. Thanks for sharing your issue. Are you using the provided CloudFormation template to run Jenkins in AWS? Or are you running it some other way?

    1. I haven’t tried this but I don’t see why not. You will have to figure out how to set the AWS credentials within the local Jenkins.

    1. When using ECS it runs Jenkins as a Docker container. This is the most straightforward approach, without having to worry about setting up the environment, which you would have to do with EC2.

  2. Hello Thanks for the wonderful article. I have question related to aws cli.

    How do I execute aws cli commands on pipeline (groovy) steps?

  3. Hi Tom,

    Thanks for sharing the video and the article. This is detailed and amazing.

    I have done this setup and ecs containers are deployed and build is getting completed.

    I have tried to store the completed builds to my S3 bucket using ‘S3 Publisher’ Jenkins plugin. However, once the build is complete, containers are deprovisioned before the s3upload in post section is initiated. Are these plugin not compatible with each other.


  4. Hi Tom,

    Thanks for sharing, this is exactly what I need. I am currently migrating my Jenkins running in ECS EC2 instance to FARGATE, this tutorial helped a lot. I just have an issue right now where I am getting the following error when I have more than one container running:

    “HTTP ERROR 403 No valid crumb was included in the request”

    I am just wondering if you have seen this error before? Your help is much appreciated. Thank you!


    1. Hi wyseman. Good to hear you’re moving your Jenkins over to the Fargate launch type.

      Are you saying you’re running multiple Jenkins masters? This approach isn’t recommended in the article. It proposes scaling horizontally by running multiple Jenkins agents.

  5. Hi Tom,

    I tried similar setup and followed your blog. every thing went well and jenkins is up and running. but the very next day when i come back and open the jenkins page i get 504 gateway time out. this is repeating all the time. first time it runs properly after a day or say prolonged ideal state the r53 url[jenkins rul] is giving 504 error.

    1. Hi Ram. Thanks for letting me know about the issue you’re having. Can you confirm you’re deploying the CloudFormation template with no modifications?

      Two more things to check:

      1. if you go to the AWS ECS dashboard and navigate to the Jenkins ECS task, how long has the task been running? Did it recently restart?
      2. do you see any errors in the Jenkins logs? You can see these in the AWS CloudWatch dashboard in a log group called ECSLogGroup-jenkins-for-ecs

      Looking forward to hearing what you find out.

  6. Hi Tom,

    This is a great Article, thank you for sharing. I think the limitation of this setup where you are unable to run docker commands/build docker images inside of your agents is pretty big! I wish that was more prominently mentioned before I went ahead and deployed the stack. Hope you have a good day!


    1. Hi Eric. Thanks for bringing this to my attention, and apologies if you were lead in the wrong direction. I’ve added a clarification to the article Running Jenkins jobs in AWS ECS with slave agents.

      Unfortunately, building Docker images isn’t supported by Jenkins slaves using Fargate. For this, I suggest using the EC2 launch type instead.

      If you’re using slave agents to run your jobs, then running the Jenkins master in Fargate is still a valid option.

  7. Hi Tom,
    Thanks for checking and replying to this plugin query. We got an existing Jenkins master agent as a docker containers concept in existing on-prem and while I was exploring Jenkins hosting on AWS cloud I came across the above-mentioned plugin and as we make use of AWS native DevOps tools like codebuild to build images & codedeploy, codepipeline as CI/CD pipeline tools, I thought of having Jenkins agents built making use of codebuild projects as agents.

    Coming to Jenkins master > codebuild as Jenkins agents, yes I am making use of codebuild with VPC enabled options with right subnets and security groups where Jenkins on EC2 instance is hosted and I opened all ports from all both source (Jenkins > codebuild > Jenkins) and destination for testing purposes on this, but it still doesn’t establish a connection from codebuild to Jenkins and it doesn’t give much information on this, still exploring on this bits. Meanwhile, if you got this plugin method option working please do let me know.

  8. Hi Tom,
    This series of articles is really helpful but I am working on a slightly different scenario which is about having Jenkins agents making use of codebuild as aws cloud agents based on this plugin – Is this something you have seen and worth considering it hosting Jenkins master as a docker container on EC2 instance? If so, can you please write an article or video demonstrating this? I tried this and it doesn’t work as expected, maybe I am missing something, I think plugin instructions aren’t clear and fails at handshake of sending a communication from codebuild back to Jenkins after initiating Jenkins agents communication from Jenkins to codebuild but fails other way and hence doesn’t work. Please check and let me know your thoughts on this.

    Many thanks in advance.

    1. Hi. I haven’t seen this plugin before but it definitely looks like an interesting option. Are you able to share your use case as to why you’ve picked this option? I think it would be interesting for readers of this article.

      Regarding your specific problem, what URL is CodeBuild using to communicate back to the Jenkins master? I don’t see any mention of that in the plugin instructions. Consider whether CodeBuild has access to the VPC in which Jenkins master is running, and if it does are the security groups setup correctly? Here’s an article about access from CodeBuild to a VPC.

  9. Hi Tom,
    Thank you very much, it was very helpful for me, as I’m installing for the first time jenkins on AWS.

    I want to know if there’s something I have to add to get docker working in a pipeline other than adding plugins.
    I’ve done everything I found on the net, and the best working from them gave me this error : Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    the solution for that I think was to add this “unix:///var/run/docker.sock” as volume, if you think that this is the solution can you give me how to add it.

    Thank you.

    1. Hi Bassem. The part of your Jenkins pipeline which needs access to Docker won’t be able to run in Fargate. That’s because you can’t mount /var/run/docker.sock into a Fargate container.

      I suggest looking into using ECS on EC2 instances or AWS CodeBuild. You can run a specific stage of your pipeline using one of these alternatives.

  10. Hi Tom,

    Good article! My question is, are you doing an EFS backup? If so, what approach are you using? For example, you made destructive changes to Jenkins master and want to restore the previous state.

    1. Hi Anton. Good question. I’ve looked into this and couldn’t find an ideal solution. I see three main options though:

      1. Design your Jenkins instance to be 100% bootstrapped i.e. all jobs & configuration are provisioned using Jenkins Configuration as Code etc. If your EFS volume is destroyed you’ll lose your job history, but you can immediately reprovision your environment. This may be good enough for some use cases.
      2. Use AWS Backup to backup EFS – it’s not 100% perfect because the backups aren’t consistent, meaning they’re not taken at a single point in time. This could cause issues if the Jenkins data goes into an inconsistent state.
      3. If consistent backups of your Jenkins really are important to you, use EBS

      Let me know what you think of these options, or if you have any other ideas.

      1. Hi Tom,
        I spent some time investigating the best approach to deploy Jenkins HA for my goals, I use the following approach:
        – Using Terraform I deploy an ECS cluster with two EC2 instances in different zones.
        – Jenkins master is working as Replica with one replica with EFS volume for Jenkins data.
        – Additional container with a backup script is working as Replica too and uses the same EFS volume. The script creates backup via rsync, first iteration – full sync, and then rsync in a loop with excluding logs till source folder(Jenkins home) and destination folder are not identities, on my test environment it takes about 5 iterations in the loop. Then script creates an archive and pushes it to S3.

  11. Tom,

    Just wanted to let you know that I found this EXTREMELY helpful in setting up our serverless Jenkins implementation. This article was very well written, easy to follow and was a real catalyst to my project.

    Keep up the good work and thank you for taking the time to share your information!


  12. Hello,
    Thanks for your tutorial, I’ve tried this in a staging environment and this seems to work wonders. I’ve adapted the cloudformation stack so I can easily add the relevant parts to an existing App load balancer. It was a bit tricky to reuse the existing infra directly via cloudformation, so I left the creation of a target group + adding the target group to the load balancer listeners as a manual operation, but the rest seems to work fine.

    However I have some speed issues sometimes, I have some suspicions that it is maybe caused by with AWS EFS (Ive seen some posts of people complaining about EFS speed in some cases), have you also observed something similar? Do you use this in production ? Do you sometimes have slow rendering speed of some jenkins page or slow API calls ?

    1. Hi Cryil. I haven’t seen this issue, but I also haven’t used this setup in any heavy-load scenarios yet. I’m wondering if you’re hitting a throughput limit on your EFS volume though.

      EFS has a base throughput and a burst throughput which you can use for short periods. Both of these are related to the current size of your volume. You can see if you have any burst credits available by checking the BurstCreditBalance metric in CloudWatch. I suggest reading through the documentation to see if it’s relevant to you. You could always try provisioned throughput mode to rule out this issue.

      Some other questions & ideas:

      • have you tried scaling up your Jenkins master CPU & memory?
      • are you running jobs on Jenkins master or using Jenkins agents?
      • how many jobs do you have running at any one time?

      If you can provide more details about your scenario I can run some more detailed tests, as I think others could benefit from the findings. Thanks for sharing your concerns.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top