# spujadas/elk-docker: the ELK image other people's compose files were copied from

> A single Dockerfile that bundles Elasticsearch, Logstash and Kibana with the init scripts and logrotate wiring most people hand-assemble badly, published to Docker Hub under the sebp/elk name.

**spujadas/elk-docker** — Elasticsearch, Logstash, Kibana (ELK) Docker image

- Repository: https://github.com/spujadas/elk-docker
- Stars: 2,164 · Forks: 897
- Language: Shell
- License: NOASSERTION
- Published: 2026-10-08 · Updated: 2026-10-08 · Language: en
- Canonical page: https://hysenlabs.com/projects/spujadas-elk-docker

## Three ports and one container

The compose file in this repository is nineteen lines and does the minimum:

```yaml
elk:
  build: .
  ports:
    - "5601:5601"
    - "9200:9200"
    - "5044:5044"
```

Those three ports are the entire interface. 5601 is Kibana's web interface, 9200 is the Elasticsearch HTTP API, and 5044 is the Beats input port that Logstash listens on. No Logstash API port, no Kibana to Elasticsearch configuration, no message queue, because the packaging decision already made those choices for you.

The Dockerfile says the same thing in a run command, which is the more useful of the two because it shows the flags that matter:

```bash
# docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk <repo-user>/elk
```

Running all three components in one container is a deliberate choice, not a shortcut, and it is the choice that makes this image different from the official per-component images. The cost is that you cannot scale Logstash independently, and you cannot restart one service without the others. For a laptop, a lab, or a small internal log server, that trade is almost always worth it. For a production ingest tier, it usually is not.

## The init scripts are the reason this image is worth using

Look at the repository tree and the value becomes obvious. Alongside the Dockerfile and the compose file there are six executables with no extension: `elasticsearch-init`, `kibana-init`, `logstash-init`, and matching `elasticsearch-logrotate`, `kibana-logrotate` and `logstash-logrotate` scripts. There are also `elasticsearch-default`, `elasticsearch.yml`, `kibana.yml`, a `pipelines.yml`, a `start.sh` and an `nginx-filebeat/` directory.

This is the part people rebuild by hand. Each Elastic component needs a config directory it can read, a data directory it can write, and a user that owns both, and the order in which those things happen at container start is a small pile of shell that nobody enjoys writing. Having it in the repository, versioned, is the point of the project.

The credentials angle is worth calling out because it is the detail that trips people up most. Elasticsearch refuses to start as root, so the Dockerfile creates a group and a user with fixed numeric identifiers, `ES_GID=991` and `ES_UID=991`, sets `ES_PATH_CONF=/etc/elasticsearch` and `ES_PATH_BACKUP=/var/backups`, and downloads the tarball rather than using a package:

```text
 ES_PACKAGE=elasticsearch-${ES_VERSION}-linux-${ARCH}.tar.gz \
 ES_GID=991 \
 ES_UID=991 \
 ES_PATH_CONF=/etc/elasticsearch \
 ES_PATH_BACKUP=/var/backups
```

Two security notes about the repository rather than the image. `logstash-beats.crt` and `logstash-beats.key` are committed at the root, which is fine for a Beat verifying the logstash certificate and wrong for anything resembling production, where you would mount your own. And the `nginx-filebeat/` directory suggests shipping nginx access logs in as a demo of the Beats path.

The repo also has a `mkdocs.yml`, a `.readthedocs.yaml` and a `docs/` directory, so the real documentation is a Read the Docs site at elk-docker.readthedocs.io rather than the README.

## Two version numbers that disagree

This is the contradiction to know about before you deploy. The README's Docker Hub section lists the tags and says `latest` and `9.0.4` both mean ELK 9.0.4, followed by `oss-9.0.4` for the OSS distribution. The Dockerfile header comment says Elasticsearch, Logstash, Kibana 9.5.4, and the build arguments agree:

```text
ARG ELK_VERSION=9.5.4
```

```text
ARG ELK_BASE_VERSION=9.5.4
```

So the published image and the source in this repository are not built from the same version claim. Both numbers are in the repository right now and neither one is going to be corrected by reading harder. The way to resolve it is to check the actual image rather than either document: pull `sebp/elk:latest` and read the version the running Elasticsearch reports, then pin an explicit tag in your own compose file.

The tag naming scheme explains itself once you see it. From 8.x onward the tag is just the ELK version, with an `oss-` prefix for the distribution without the default features, and every 8.x release is available in both forms. Before that the tags encode the three component versions separately, `es233_l232_k451` meaning Elasticsearch 2.3.3, Logstash 2.3.2 and Kibana 4.5.1. The README notes that you can pull specific combinations of the three versions.

The back catalogue is long: 7.17 down through 7.0 in both flavours, the whole 6.x line as bare numeric tags, 5.x down to `es500_l500_k500`, and the 2.x and 1.x era as `es241_l240_k461` down to `E1L1K4`. The one oddity is the `7.17.1` entry, which the README describes twice and once maps to ELK 7.17.5.

## Build arguments, ARM support and an old base image

The Dockerfile is parameterised more than you would expect, and the parameters are where most of the real decisions sit. `ARG IMAGE=focal-1.1.0` selects the phusion/baseimage base, `ARG ARCH=x86_64` chooses between x86_64 and aarch64 tarballs, and the inline comments tell you to swap in `master-arm64` or `aarch64` for Apple Silicon or ARM servers.

The base image line is worth pausing on. phusion/baseimage focal is Ubuntu 20.04, and the Dockerfile still installs `openjdk-11-jdk-headless` as a prerequisite for Logstash, along with ca-certificates, curl, gosu and tzdata. There is an `ENV REFRESHED_AT=2020-06-20` marker in the file, and `gosu` is doing the work of dropping privileges that a modern image would do with a plain `USER` instruction. This is an image built in an era when that was the normal way to do it, and the combination of focal plus JDK 11 alongside a 9.x stack is the kind of thing to verify on your own host rather than assume.

The version split between `ELK_VERSION` and `ELK_BASE_VERSION` is a historical scar worth understanding. The comment on the base version says it is the version with the OSS prefix removed, for Elasticsearch and Kibana, and adds that there is no OSS version since 7.11.0. That is why the `oss-` tags stop appearing in the modern range: the split distribution ended, so `oss-9.0.4` refers to something different from `9.0.4` in a way that `oss-9.5.4` no longer needs to.

The build itself is ordinary: update apt quietly, install the prerequisites with `--no-install-recommends`, clean the package lists, and verify the `gosu nobody true` call works before proceeding. Nothing exotic, but each of those lines is there because its absence broke something at some point.

## Conclusion

elk-docker earns its place on the parts of ELK deployment that people get wrong by hand: running the three services as one container, running each as its own unprivileged user, and shipping the init scripts and logrotate configuration alongside the images. The three ports are the whole interface, 5601 for Kibana, 9200 for Elasticsearch and 5044 for Beats input. Before you deploy it, check the version number against your needs, because the README advertises `latest` as 9.0.4 while the Dockerfile in the repository pins its build arguments to 9.5.4, and pick a tag deliberately rather than tracking `latest`. The `oss-` tags exist for every 8.x release, which matters if you cannot run the default distribution with its bundled X-Pack features. Start with the compose file in this repository, which builds locally on port 5601, and read the Read the Docs pages for the init script behaviour.

## FAQ

### What is elk and how does it work?

ELK is Elasticsearch, Logstash and Kibana packaged together: Elasticsearch stores and indexes, Logstash ingests and transforms, and Kibana is the web interface for searching. This image runs all three in one container and publishes Kibana on 5601, Elasticsearch on 9200 and Logstash Beats input on 5044.

### Is elk the same as Elasticsearch?

No. Elasticsearch is one of the three components, the storage and search engine at the core. This image bundles it with Logstash for ingest and Kibana for the interface, so pulling this image gets you all three rather than a different flavour of Elasticsearch.

### Which Docker Hub tag should I use?

Pin an explicit version rather than tracking `latest`, since the README and the Dockerfile in this repository name different versions for it. Every 8.x release has a plain tag and an `oss-` variant, and older tags encode the three component versions separately, like `es233_l232_k451`.

### Does this image run each service as a separate user?

The Dockerfile creates a dedicated group and user for Elasticsearch with fixed identifiers, 991 for both, because Elasticsearch refuses to start as root, and gosu is installed to drop privileges for the other components. Init scripts and logrotate configuration for all three services sit at the repository root.

## Sources

- [Issues](https://github.com/spujadas/elk-docker/issues)
- [README](https://github.com/spujadas/elk-docker/blob/master/README.md)
- [Releases](https://github.com/spujadas/elk-docker/releases)
- [spujadas/elk-docker on GitHub](https://github.com/spujadas/elk-docker)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spujadas-elk-docker
