MySQL server

Real-world MySQL 5.7 Dockerfile from sameersbn/docker-mysql, a widely used community MySQL image.

← Examples

Source: GitHub

8 issues foundCritical: 1High: 2Medium: 2Low: 3Recommendations: 3
DockerfileLines with findings are highlighted
SHA-256:
1FROM ubuntu:bionic-20190612Critical
2LABEL maintainer="sameer@damagehead.com"
3ENV MYSQL_USER=mysql MYSQL_VERSION=5.7.26 MYSQL_DATA_DIR=/var/lib/mysql MYSQL_RUN_DIR=/run/mysqld MYSQL_LOG_DIR=/var/log/mysql
4RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server=${MYSQL_VERSION}* && rm -rf ${MYSQL_DATA_DIR} && rm -rf /var/lib/apt/lists/*Medium
5COPY entrypoint.sh /sbin/entrypoint.sh
6RUN chmod 755 /sbin/entrypoint.shLow
7EXPOSE 3306/tcpMedium
8ENTRYPOINT ["/sbin/entrypoint.sh"]Low
9CMD ["/usr/bin/mysqld_safe"]
Findings
8 issues found
FROM ubuntu:bionic-20190612
Base image severely outdated
The base image has not been updated in a very long time: for :latest and untagged images the threshold is 60 days; for pinned version tags (e.g. node:20, alpine:3.18) the threshold is 180 days. A severely stale base image is very likely to contain unpatched CVEs. Rebuild with docker build --pull, switch to a more recently maintained image, or pin to a digest once you have verified the current state.
CriticalBase Image
FROM ubuntu:bionic-20190612
High CVEs in base image
The base image has one or more high-severity CVEs according to Docker Scout, and no critical ones. High vulnerabilities are often exploitable and may allow privilege escalation or data exposure. Update to a patched image version or switch to a more secure base image. Note: CVE data is sourced from Docker Scout at the time of the last data rebuild — coverage is not guaranteed to be complete, and a clean result does not confirm the image is free of CVEs.
HighBase Image
Container user
User root
The final container is running under the context of the root user.
# Create a dedicated non-root user and switch to it before CMD/ENTRYPOINT RUN useradd --create-home --shell /bin/bash appuser USER appuser
HighUser
RUN apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server=${MYSQL_VERSION}* \
  && rm -rf ${MYSQL_DATA_DIR} \
  && rm -rf /var/lib/apt/lists/*
Apt-family install, but no upgrade
An apt-family tool (apt, apt-get, aptitude, dpkg) is used to install packages but upgrade was not called first to patch existing packages.
RUN apt-get update && apt-get upgrade -y \ && apt-get install -y --no-install-recommends <packages> \ && rm -rf /var/lib/apt/lists/*
MediumPackage Manager
EXPOSE 3306/tcp
Database port exposed directly
The Dockerfile exposes a database service port (MySQL 3306, MSSQL 1433, PostgreSQL 5432, MongoDB 27017, or Redis 6379) directly. Database services should not be reachable outside the container network. Exposing these ports risks unintended network exposure when published via compose or an orchestrator, bypasses application-layer access controls, and makes the database a direct attack target. Access the database through the application tier rather than publishing its port.
Medium
FROM ubuntu:bionic-20190612
FROM without image digest
The base image is referenced by tag rather than by digest. Tags are mutable — the same tag can be silently updated to point to a different image. Pinning to a digest (e.g. image:tag@sha256:...) guarantees you always build from exactly the image you reviewed. If you rebuild frequently with docker build --pull, the freshness risk is lower — though supply-chain reproducibility still benefits from digest pinning. Note: digest-pinning fixes the image layer but does not protect against newly-discovered CVEs in that layer — vulnerability scanning should still be performed regularly even when digests are in use.
LowBase Image
RUN chmod 755 /sbin/entrypoint.sh
World-readable permissions set
The other-read bit is set without the other-write bit. Any process running as any user can read the file. Sensitive files such as private keys, credentials, or configuration should not be world-readable.
# Restrict sensitive files to owner-only read RUN chmod 600 /app/config/secrets.conf
LowPermissions
ENTRYPOINT ["/sbin/entrypoint.sh"]
Executes a copied-in script not analysed by DockerSec
A shell script is copied into the image (COPY/ADD) and then executed by a RUN, ENTRYPOINT, or CMD instruction. DockerSec analyses the Dockerfile only; the script contents are not inspected, so security-relevant operations inside it (package installs, credential handling, network configuration, privilege changes) are not covered by this scan. There is latent risk here: review the script manually. Where practical, inline the script logic into the Dockerfile so it can be analysed, or keep the script minimal and audited.
Low

RUN apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server=${MYSQL_VERSION}* \
  && rm -rf ${MYSQL_DATA_DIR} \
  && rm -rf /var/lib/apt/lists/*
apt-get install without --no-install-recommends
apt-get install is called without --no-install-recommends. Without this flag, apt installs recommended packages in addition to those explicitly requested, unnecessarily increasing image size and attack surface. Add --no-install-recommends to install only what is needed: RUN apt-get install -y --no-install-recommends <packages>
Package Manager
RUN apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server=${MYSQL_VERSION}* \
  && rm -rf ${MYSQL_DATA_DIR} \
  && rm -rf /var/lib/apt/lists/*
apt-get install with a wildcard version pin
apt-get install pins a package version with a trailing wildcard (for example pkg=1.2.*), so the exact build is still selected at install time from whatever matches. This is better than no pin, but the build is not fully reproducible and an unexpected matching version can be pulled on a rebuild. Pin the exact version (e.g. nginx=1.18.0-0ubuntu1) for reproducible builds.
Package Manager
No HEALTHCHECK defined
No HEALTHCHECK defined in final stage
The final image stage does not define a HEALTHCHECK instruction. Without one, container orchestrators and the Docker daemon cannot distinguish a running container from one that is alive but unhealthy (deadlocked, crashed dependencies, etc.), increasing the risk of traffic being routed to a broken container. Add a HEALTHCHECK CMD instruction that tests whether the application is functioning correctly. Note: if the base image already defines a HEALTHCHECK it will be inherited, but this cannot be verified from the Dockerfile alone.