Use es-python in a container
How to build es-python into a container image with a Dockerfile, so that your program runs under es-python whenever the container starts, and what to keep in mind when many containers share one image.
The recipe
Install es-python while the image builds, with your API key passed in as a build secret, then make es-python the entry point. A build secret is mounted for the one step that needs it and is never written into a layer of the image.
# syntax=docker/dockerfile:1
FROM python:3.13-slim-bookworm
# The installer needs curl; slim images do not include it.
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Install es-python. The key is read from the build secret for this step only.
RUN --mount=type=secret,id=eyalsec_api_key \
curl -fsSL https://eyalsec.com/ci.sh -o /tmp/es-python-ci.sh \
&& EYALSEC_API_KEY="$(cat /run/secrets/eyalsec_api_key)" \
sh /tmp/es-python-ci.sh install --machine my-service \
--distro debian_12 --arch x86_64 \
&& rm -f /tmp/es-python-ci.sh
ENV PATH="/root/.local/bin:${PATH}"
# Sources on by default; an explicit On or Off on the dashboard still wins.
ENV ES2_MAKE_SOCKET_VULN=1 ES2_MAKE_FILE_VULN=1
COPY . .
ENTRYPOINT ["es-python"]
CMD ["app.py"]
Build it with the key from your environment (or from your CI secret store) as the secret:
docker build --secret id=eyalsec_api_key,env=EYALSEC_API_KEY -t my-service .
--secret ... env= needs a recent Docker with BuildKit; on an older one, write the key to a file outside the build context and use --secret id=eyalsec_api_key,src=/path/to/key instead.
What each part does:
- Same Python version as the image. es-python shares the packages of the regular Python of the same version, so
pip installinto the image's Python 3.13 is enough, and the install step must come after it. See Packages. For another version, start from thatpython:3.Ximage and add--python-version 3.Xthe first time. --distroand--archdescribe the image, not the computer that builds it:python:3.13-slim-bookwormisdebian_12. Build on the architecture you name (or with--platform).ENV PATHputses-pythonon the path. The installer installs into the home directory of the user that runs it, which is/roothere.ENTRYPOINT ["es-python"]runs every container's program under es-python.docker run my-service other.pyrunses-python other.py.
For a non-root image, switch to that user (USER app) before the install step and set PATH to that user's ~/.local/bin, so es-python is installed for the user that will run it.
Without the API key in the build
If your build may not hold the API key, get a one-time install secret outside the build and pass only that in. The CI API or the Machines page gives you one; it works once and expires after 10 minutes, so build right after you get it.
RUN --mount=type=secret,id=eyalsec_install \
curl -sSL -d "secret=$(cat /run/secrets/eyalsec_install)" \
--data-urlencode "glibc=$(ldd --version 2>/dev/null | head -1)" \
--data-urlencode "arch=$(uname -m)" \
https://eyalsec.com/install.sh | bash
Things to know
Read these before you ship an image to many hosts.
- Every container from one image is the same machine. They all report under the one machine name you installed, so the Events page cannot tell two containers apart. Use one machine per service (one image), not one per container.
- Containers can look like copies of one install. EyalSec checks that a machine's install keeps running on the computer it was installed on, and each new container is, to that check, a different computer. Several containers from one image, or a container replaced by a new one, can therefore put the clone badge on the machine. The recipe suits a service that runs as one container at a time, such as a test or staging deployment; if the machine shows clone, this is the reason, and rebuilding the image (which reinstalls the machine) clears it.
- A new build replaces the old one's credential. Building the image again reinstalls the machine, and once that install starts, containers still running an older build of the image stop reporting. Roll out the new image, or use a different machine name per image version if both must report at once. A build that reuses a cached install layer does not reinstall.
- The image holds a working machine credential. Anyone who has the image can report events into that machine. Keep the image in a private registry, as you would any image with credentials in it.
- Keep the API key out of the image. Not in an
ENV, anARGor a copied file: those end up in the image's layers or history. Use--mount=type=secretas shown. - The machine counts toward your limit once, however many containers run from the image. See Machine limit.
- Sources are environment defaults in the image; change them per container with
-e, for exampledocker run -e ES2_MAKE_ENV_VULN=1 my-service, or on the dashboard. See es-python command line.
To run your test suite under es-python in a pipeline instead, see Run es-python in CI.