Amazon ECS Container Agent: four installs, one env file
Amazon Elastic Container Service Agent
At a glance
- What is it?
- The Amazon ECS Container Agent is the node-side half of ECS, and how you install it decides who restarts it when it dies: systemd through ECS-Init, a Docker container with a restart policy, a Windows service installed by PowerShell, or a standalone binary AWS tells you not to use in production. Each path also carries its own environment flags.
- Who is it for?
- Use the ECS-Init package on Amazon Linux, the documented deb or rpm elsewhere, and ECSTools on the Windows AMI, because those are the paths with a supervisor attached. Reach for the Docker container only when you want the agent beside a Docker daemon you control, and mind that it mounts the daemon socket and needs route_localnet plus two NAT rules on the host.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What runs on the node, and who keeps it alive
The Amazon ECS Container Agent is the part of ECS that runs on your instance and manages containers on behalf of the service. It is not the control plane. It is the process that polls for work, pulls images, wires up networking for a task and reports status back, and everything in this repository is downstream of those jobs.
The repository ships more than the agent. It also carries ECS-Init, a systemd-based service whose job is to support the agent and keep it running, packaged as a deb or an rpm, with its source under `ecs-init` and the packaging under `packaging`. That distinction is the single most useful thing in the README, because it means the agent binary and its supervisor are versioned together and packaged separately.
On the Amazon Linux AMI the documented path is a single command pair, and it is described as the recommended way to run the agent in that environment:
sudo yum install ecs-init && sudo start ecsElsewhere on Linux, the ECS documentation carries deb and rpm packages and instructions. On the ECS Optimized Windows AMI, the agent is installed with a PowerShell module named ECSTools that is pre-installed on the image and registers the agent as a Windows service. Four install paths, four different failure stories, and that is the subject of the next comparison rather than an afterthought.
One thing the README is upfront about: the ECS documentation is the best source of information on running this software. The repository is the source, not the manual.
169.254.170.2, route_localnet and the two NAT rules
This is the part worth understanding before you copy a command, because it explains why the Docker example needs host-level networking changes at all.
mkdir -p /var/log/ecs /etc/ecs /var/lib/ecs/data
touch /etc/ecs/ecs.config
sysctl -w net.ipv4.conf.all.route_localnet=1
iptables -t nat -A PREROUTING -p tcp -d 169.254.170.2 --dport 80 -j DNAT --to-destination 127.0.0.1:51679
iptables -t nat -A OUTPUT -d 169.254.170.2 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679The README introduces the sysctl and iptables lines as the rules needed to enable IAM roles for tasks. The address they cover, 169.254.170.2 on port 80, is link-local, which is the root of the difficulty: a container in its own network namespace cannot route to a link-local address on the host without help. So the host enables localnet routing, DNATs inbound traffic to that address into the agent's own port 51679, and redirects locally generated traffic the same way. The address and the port are doing the same job on both sides, which is why one of the rules is PREROUTING and the other is OUTPUT.
Then the agent itself runs as a container, with the Docker socket bind-mounted and host networking:
docker run --name ecs-agent \
--detach=true \
--restart=on-failure:10 \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/log/ecs:/log \
--volume=/var/lib/ecs/data:/data \
--net=host \
--env-file=/etc/ecs/ecs.config \
--env=ECS_LOGFILE=/log/ecs-agent.log \
--env=ECS_DATADIR=/data/ \
--env=ECS_ENABLE_TASK_IAM_ROLE=true \
--env=ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \
amazon/amazon-ecs-agent:latestThree flags carry the design. `ECS_ENABLE_TASK_IAM_ROLE` is the switch the earlier rules exist to support, and `ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST` is what allows task roles to work while the agent itself is on host networking. And `--restart=on-failure:10` is the entire supervision story for this path: ten retries, then the agent stays down until something notices. Notice also that the agent owns the Docker daemon on that host, through the mounted socket. That is how ECS runs containers, and it is worth being explicit about before you install it.
Four ways to keep the same agent alive
The interesting comparison is not between agents but between supervisors. The binary is the same in all four cases.
Under ECS-Init, systemd owns the process. It starts on boot, restarts on failure without a retry ceiling you configure by hand, and reports through `journalctl` like anything else on the machine. This is the recommended path on the Amazon Linux AMI, and the packaging work under `packaging/` exists to make it one command.
In Docker, the daemon owns the process, and the policy is the `--restart=on-failure:10` flag. It is a bounded policy: after ten consecutive failures the container stays stopped. That is a deliberate trade, since the alternative is a crash loop that hides a real fault, but it means an unattended node can stay without an agent until something external intervenes.
On Windows, ECSTools registers the agent as a Windows service, so the Windows SCM owns recovery. The PowerShell surface also does version pinning, which is the one place in the README where you choose an agent version rather than tracking `latest`.
And there is a fourth option the README explicitly discourages: running the agent as a plain Go binary outside a container. It calls that useful for development and for integration with local Go tools, and says it is not recommended for production on Linux. That sentence is the whole argument for the packaged paths, and it is worth reading as the project author writing it rather than as boilerplate.
There is also a fallback path worth knowing: the Amazon ECS documentation also carries images in the Docker Hub repository and in the ECR Public Gallery, which is how you avoid pulling from a registry you do not control.
awsvpc mode is a different installation, not a flag
Turn on the AWS VPC networking mode and the requirements change shape. The agent needs a CNI plugin and dhclient to be available, and ecs-init has to run as part of startup rather than being an afterthought. The README also states one flat limitation: the agent currently only supports cgroupfs as the cgroup driver, so a host configured for the systemd cgroup driver is outside what this component supports.
The container invocation grows to match. Volumes appear for `/sbin`, `/lib`, `/lib64`, `/usr/lib`, `/usr/lib64`, `/proc` and `/sys/fs/cgroup`, which is the agent borrowing enough of the host to manage cgroups and processes on its behalf. Two capabilities are added, and the environment block carries the settings that make the mode work:
--cap-add=sys_admin \
--cap-add=net_admin \
--env ECS_ENABLE_TASK_ENI=true \
--env ECS_UPDATES_ENABLED=true \
--env ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION=1h \
--env ECS_DATADIR=/data \
--env ECS_ENABLE_TASK_IAM_ROLE=true \
--env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \
--env ECS_LOGFILE=/log/ecs-agent.log \
--env ECS_AVAILABLE_LOGGING_DRIVERS='["json-file","awslogs","syslog","none"]' \
--env ECS_LOGLEVEL=info \`ECS_ENABLE_TASK_ENI` is the task ENI switch. `ECS_UPDATES_ENABLED` lets the agent update itself, which is convenient on an instance nobody logs into and another thing running on your nodes without you asking. `ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION=1h` sets how long the engine waits before cleaning up, and the logging drivers list is where you decide whether container logs go to `awslogs`, the Docker json file, syslog or nowhere at all.
The security posture here is worth naming plainly. `sys_admin` and `net_admin` plus host cgroups and `/proc` is close to full host control, which is inherent to a component that creates containers rather than a criticism of the configuration.
Pinning an agent version and building the image yourself
On Windows, pinning a version is a first-class operation, which is worth copying in spirit to Linux even though the README does not offer it there:
Import-Module ECSTools
Initialize-ECSAgent -Cluster 'windows' -EnableTaskIAMRoleThe cluster name is a parameter, so the same command launches the agent into any cluster you name. `-EnableTaskIAMRole` is required to enable IAM roles for tasks, and the README says so in a comment on the line itself. For an older agent, set the version first and pass it through:
$agentVersion = "v1.20.4"
Initialize-ECSAgent -Cluster 'windows' -EnableTaskIAMRole -Version $agentVersionThe value `latest` selects the newest available version, so the two-line form is also how you upgrade.
Building the Linux image from source is three commands. Clone the repository, then run the `release-agent` target, which installs the build dependencies, builds the image and writes it to a tar file named after the agent version:
git clone https://github.com/aws/amazon-ecs-agent.git
make release-agent
docker load < ecs-agent-v${AGENT_VERSION}.tarLoading that tar gives you a local image you can then run with the earlier command, which is the sensible way to test a change without publishing anything. For Windows the equivalent is `scripts\build_agent.ps1`, and there is a separate set of PowerShell helpers: an integration test runner for the `engine` and `stats` packages, a service installer under `misc\windows-deploy`, and sample user-data for a Windows Server 2016 with Containers AMI.
The ECS-Init package has its own build instructions too, one path for a deb and one for an rpm under `packaging/`.
Two version files, two changelogs and a Makefile that picks your arch
The build system has a few decisions that explain how the project supports three targets from one tree.
The architecture is chosen from the machine you build on: `uname -m` reporting `aarch64` sets `GOARCH=arm64`, anything else sets `amd64`. The Go toolchain is read from a file rather than hardcoded, and there are two of them, `GO_VERSION` and `GO_VERSION_WINDOWS`, so a Windows build can sit on a different compiler release than a Linux build without a branch in the Makefile:
GO_VERSION=$(shell cat ./GO_VERSION_WINDOWS)
export GO111MODULE=auto
VERSION = $(shell cat ecs-init/ECSVERSION)Those three lines also explain why two changelogs exist. The Makefile reads the version from `ecs-init/ECSVERSION`, while a separate `VERSION` file and a separate `INIT_CHANGELOG.md` sit alongside `CHANGELOG.md`, so the agent and its init wrapper are released on their own clocks.
The `gobuild` target is deliberately dynamic, described in a comment as not passing `-a` so it does not recompile everything on every invocation. The `static` and `xplatform-build` targets exist for static analysis, and the cross-platform one checks both of the primary pairs:
xplatform-build:
GOOS=linux GOARCH=arm64 ./scripts/build true "" false
GOOS=windows GOARCH=amd64 ./scripts/build true "" falseEverything lands under `out/`, including separate directories for test artifacts, CNI plugins and the two VPC CNI plugin trees, which are created through a stamp file so the directories are made once.
The rest of the tree tells you what is vendored and what is generated. `aws-sdk-go-v2/` and both CNI plugin trees are checked in alongside `.gitmodules`, so a build has the SDK without a network fetch. `NOTICE` sits next to `LICENSE`, which is the Apache-2.0 convention for required attribution notices, and `seelog.xml` is the logging configuration the agent reads. Build and publish machinery is described in `buildspec.yml` with ECR replication and ECR upload variants, and there are `proposals/` and `.kiro/` directories for design work and agent configuration.
Where the ECS agent is the wrong tool
The scope is narrow on purpose, and outside it this component is the wrong answer. It manages containers for Amazon ECS. If you want Kubernetes, a Nomad cluster or a plain Docker Compose stack, none of this applies, because the agent exists to implement one scheduler's task definitions.
Then there are the constraints that do bite. Only cgroupfs is supported as the cgroup driver, which rules out a host on the systemd cgroup driver. awsvpc needs a CNI plugin, dhclient and ecs-init at startup, so it is a different installation rather than a configuration toggle. The Docker path gives you a bounded restart policy, so an unattended node can end up without an agent.
Two more practical limits. The Docker examples in the README pin `:latest`, and while the Windows path documents pinning a version, the Linux path in this page does not, so a node built from the README tracks whatever the registry currently serves unless you change the tag yourself. And the agent runs with control of the Docker daemon socket, which is how it starts containers, but it does mean the agent is a high-value process on that host and belongs in the same hardening review as the daemon itself.
Finally, the standalone binary. It is genuinely useful for development and for working with local Go tooling, and the README says outright that it is not recommended for production on Linux. If you are weighing it for a real node, the answer is already in the documentation.
Editorial conclusion
Use the ECS-Init package on Amazon Linux, the documented deb or rpm elsewhere, and ECSTools on the Windows AMI, because those are the paths with a supervisor attached. Reach for the Docker container only when you want the agent beside a Docker daemon you control, and mind that it mounts the daemon socket and needs route_localnet plus two NAT rules on the host. Skip the standalone `./out/amazon-ecs-agent` binary in production, as the README says, and check cgroupfs before planning an awsvpc deployment, because no other cgroup driver is supported.
Frequently asked questions
How do I install the Amazon ECS Container Agent on Amazon Linux?
Install the ECS-Init RPM and start the service: `sudo yum install ecs-init && sudo start ecs`, which the README calls the recommended way to run the agent in that environment. ECS-Init is a systemd service that supports the agent and keeps it running, with its source under ecs-init and the packaging under packaging.
Can I run the Amazon ECS agent in a Docker container?
Yes, with images in the Docker Hub repository and the ECR Public Gallery. The documented run mounts /var/run/docker.sock, /var/log/ecs and /var/lib/ecs/data, uses --net=host and --env-file=/etc/ecs/ecs.config, and on the host requires sysctl net.ipv4.conf.all.route_localnet=1 plus DNAT and REDIRECT rules for 169.254.170.2 port 80 so task IAM roles work.
How do I install the ECS agent on the ECS Optimized Windows AMI?
The AMI ships a PowerShell module called ECSTools that installs, configures and runs the agent as a Windows service. Run `Import-Module ECSTools` then `Initialize-ECSAgent -Cluster 'windows' -EnableTaskIAMRole`, and add `-Version $agentVersion` to pin a version such as v1.20.4, where the value latest selects the newest available.
Does the Amazon ECS agent support awsvpc networking mode?
Yes, but it requires a CNI plugin and dhclient to be available, and ecs-init has to run as part of startup. The README also states that the agent currently only supports cgroupfs as the cgroup driver.
How do I build the Amazon ECS agent from source?
Clone the repository and run `make release-agent`, which installs the build dependencies and writes ecs-agent-v${AGENT_VERSION}.tar, then load it with `docker load`. For a standalone binary use `make gobuild` and run ./out/amazon-ecs-agent, which the README says is not recommended for production on Linux. Windows builds through scripts\build_agent.ps1.
What licence is the Amazon ECS agent released under?
Apache-2.0, with the LICENSE file at the top level and a NOTICE file beside it as the licence requires. The agent, ECS-Init and their packaging are all in this repository, so one licence covers the binary and the systemd wrapper.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/aws-amazon-ecs-agent)