Docker Image – FROM, RUN, COPY, ENTRYPOINT, CMD, EXPOSE

dockerfile FROM RUN COPY ENTRYPOINT CMD EXPOSE
Table of Contents Hide
  1. Please explain Docker Image clearly

Today we will learn everything about docker image. You might wonder how a Dockerfile creates an Image which runs a container. We will see all the commands which are used in Dockerfile like FROM, RUN, COPY, ENTRYPOINT, CMD, EXPOSE etc.

Please explain Docker Image clearly

Sure. Docker image is a bundle which is used to run a piece of software. In one sense, this is everything. If you want to run MySql, there will be a docker image for it.

This docker image consists of a Dockerfile which holds instructions which we call layers.

This is the Dockerfile for Mysql for version 8.0 –

#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM oraclelinux:8-slim

RUN set -eux; \
	groupadd --system --gid 999 mysql; \
	useradd --system --uid 999 --gid 999 --home-dir /var/lib/mysql --no-create-home mysql

# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; \
# TODO find a better userspace architecture detection method than querying the kernel
	arch="$(uname -m)"; \
	case "$arch" in \
		aarch64) gosuArch='arm64' ;; \
		x86_64) gosuArch='amd64' ;; \
		*) echo >&2 "error: unsupported architecture: '$arch'"; exit 1 ;; \
	esac; \
	curl -fL -o /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$gosuArch.asc"; \
	curl -fL -o /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$gosuArch"; \
	export GNUPGHOME="$(mktemp -d)"; \
	gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
	chmod +x /usr/local/bin/gosu; \
	gosu --version; \
	gosu nobody true

RUN set -eux; \
	microdnf install -y \
		bzip2 \
		gzip \
		openssl \
		xz \
		zstd \
# Oracle Linux 8+ is very slim :)
		findutils \
	; \
	microdnf clean all

RUN set -eux; \
# https://dev.mysql.com/doc/refman/8.0/en/checking-gpg-signature.html
# gpg: key 3A79BD29: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
	key='859BE8D7C586F538430B19C2467B942D3A79BD29'; \
	export GNUPGHOME="$(mktemp -d)"; \
	gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
	gpg --batch --export --armor "$key" > /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql; \
	rm -rf "$GNUPGHOME"

ENV MYSQL_MAJOR 8.0
ENV MYSQL_VERSION 8.0.29-1.el8

RUN set -eu; \
	. /etc/os-release; \
	{ \
		echo '[mysql8.0-server-minimal]'; \
		echo 'name=MySQL 8.0 Server Minimal'; \
		echo 'enabled=1'; \
		echo "baseurl=https://repo.mysql.com/yum/mysql-8.0-community/docker/el/${VERSION_ID%%[.-]*}/\$basearch/"; \
		echo 'gpgcheck=1'; \
		echo 'gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql'; \
# https://github.com/docker-library/mysql/pull/680#issuecomment-825930524
		echo 'module_hotfixes=true'; \
	} | tee /etc/yum.repos.d/mysql-community-minimal.repo

RUN set -eux; \
	microdnf install -y "mysql-community-server-minimal-$MYSQL_VERSION"; \
	microdnf clean all; \
# the "socket" value in the Oracle packages is set to "/var/lib/mysql" which isn't a great place for the socket (we want it in "/var/run/mysqld" instead)
# https://github.com/docker-library/mysql/pull/680#issuecomment-636121520
	grep -F 'socket=/var/lib/mysql/mysql.sock' /etc/my.cnf; \
	sed -i 's!^socket=.*!socket=/var/run/mysqld/mysqld.sock!' /etc/my.cnf; \
	grep -F 'socket=/var/run/mysqld/mysqld.sock' /etc/my.cnf; \
	{ echo '[client]'; echo 'socket=/var/run/mysqld/mysqld.sock'; } >> /etc/my.cnf; \
	\
# make sure users dumping files in "/etc/mysql/conf.d" still works
	! grep -F '!includedir' /etc/my.cnf; \
	{ echo; echo '!includedir /etc/mysql/conf.d/'; } >> /etc/my.cnf; \
	mkdir -p /etc/mysql/conf.d; \
# ensure these directories exist and have useful permissions
# the rpm package has different opinions on the mode of `/var/run/mysqld`, so this needs to be after install
	mkdir -p /var/lib/mysql /var/run/mysqld; \
	chown mysql:mysql /var/lib/mysql /var/run/mysqld; \
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
	chmod 1777 /var/lib/mysql /var/run/mysqld; \
	\
	mkdir /docker-entrypoint-initdb.d; \
	\
	mysqld --version; \
	mysql --version

RUN set -eu; \
	. /etc/os-release; \
	{ \
		echo '[mysql-tools-community]'; \
		echo 'name=MySQL Tools Community'; \
		echo "baseurl=https://repo.mysql.com/yum/mysql-tools-community/el/${VERSION_ID%%[.-]*}/\$basearch/"; \
		echo 'enabled=1'; \
		echo 'gpgcheck=1'; \
		echo 'gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql'; \
# https://github.com/docker-library/mysql/pull/680#issuecomment-825930524
		echo 'module_hotfixes=true'; \
	} | tee /etc/yum.repos.d/mysql-community-tools.repo
ENV MYSQL_SHELL_VERSION 8.0.29-1.el8
RUN set -eux; \
	microdnf install -y "mysql-shell-$MYSQL_SHELL_VERSION"; \
	microdnf clean all; \
	\
	mysqlsh --version

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

This image will create a container which will run MySql. Every individual step is a layer.

Let’s understand each instruction of this Dockerfile –

FROM

FROM indicates the base image on which this container resides. Each and every image will have a base image. So, for mysql, the base image is oraclelinux. It’s a linux based operating system by Oracle. If you open the Dockerfile of oraclelinux, you will find that it is dependent on some other image. The most fundamental image is scratch, which is empty and provided by docker for a start.

RUN

RUN instruction is used to run commands in the terminal of the container. You can run shell scripts and nearly all the linux commands which container is supporting. So, with this instruction, you can install libraries, essential software and much more.

ENV

ENV will help you in setting an environment variable in your container. So, you can set usernames, passwords, API keys or anything which is worth setting as environment variable.

VOLUME

VOLUME instruction indicates that the data files will be stored in given directory. In mysql, it is indicated that the database files will be store at /var/lib/mysql.

COPY

COPY instruction is used to copy something from host machine to a container directory. You might be wondering why we didn’t use RUN instruction with cp command of linux? Why use a separate COPY instruction. This is because cp will copy a file within container only. Remember, RUN instruction is used to run commands inside container terminal. So, it can’t be used to transfer stuff from host node. That’s why we use COPY instruction.

EXPOSE

EXPOSE is used to open ports on container. This is very handy as we can open the required ports only and keep our container safe.

ENTRYPOINT

ENTRYPOINT instruction is used to start a command or script every time the container starts. It supports extra parameters which we can pass while running the container. For example, in our mysql image, we can pass the username, password and even the database name while running the container. So ENTRYPOINT will run docker-entrypoint.sh and pass the provided parameters to it. You can not override this from run command. A Dockerfile can have only one ENTRYPOINT instruction.

CMD

CMD is similar to the ENTRYPOINT but you can override it completely while running container.