Docker is an environment to run small isolated virtual machines called containers.
Container are stateless, which means they don’t store the state of the application or data created during the runtime. Any changes made to filesystem within a container are temporary and will be lost forever if you stop, restart or remove container! Stateless design ensures that containers are lightweight, portable, and self-sufficient and you can start or move between servers without affecting the application’s functionality or causing any discrepancies in data.
Container should be run from a snapshot of working application with all the environment, dependencies and application itself included in it. This snapshot has name of docker image. Script containing steps required to build a Docker container image called Dockerfile. The script might operate a very limited set of commands.
List of available Dockerfile commands:
- FROM: Specifies the base image to build the new container image from.
- RUN: Executes commands in a new layer on top of the current image and commits the results.
- COPY: Copies files or directories from the host system into the container.
- ADD: Similar to COPY, but also allows fetching remote files or unpacking archives directly into the image.
- CMD: Specifies the default command to run when the container is started.
- ENTRYPOINT: Specifies the command that will always be executed when the container starts, regardless of the CMD instruction.
- ENV: Sets environment variables in the container.
- EXPOSE: Indicates the network ports the container will listen on at runtime.
- VOLUME: Creates a mount point in the container for persistent or shared data.
- WORKDIR: Sets the working directory for subsequent instructions in the Dockerfile.
To build a Docker container image from a Dockerfile, you use the
docker build command followed by a build context (usually a local directory containing the Dockerfile). Once the image is built, you can run containers from it using the
docker run command.
Creating a basic Dockerfile
Lets create a basic Docker image with NodeJS. First create a file called
Dockerfile (without extension). Open it with any text editor (I always recommend VSCode) and place the following:
# Use the latest official Node.js runtime as a parent image FROM node:latest # Set the working directory to /app WORKDIR /app # Copy the package.json file into the container at /app COPY package.json /app # Install any needed packages specified in package.json RUN npm install # Copy the rest of the application code into the container at /app COPY . /app # Make port 3000 available to the world outside this container EXPOSE 3000 # Run app.js when the container launches CMD ["node", "app.js"]
Save the file and try to build the image:
docker build -t your-image-name .
You should have an error:
docker build -t your-image-name . ⬡ 18.16.0 [+] Building 1.7s (8/10) => [internal] load build definition from Dockerfile => [internal] load metadata for docker.io/library/node:latest => [auth] library/node:pull token for registry-1.docker.io => [internal] load build context => => transferring context: 539B => [1/5] FROM docker.io/library/node:[email protected]:242d81ad2a91353ac3a5ed3598582acb4a9a7761b16c60524b949a1603707848 => => sha256:4e271ab266a4b76874c8e7c8aa431a8dbe636af19fa5e76403e3acbd9b8d3450 2.21kB / 2.21kB => CACHED [2/5] WORKDIR /app => ERROR [3/5] COPY package.json /app ------ > [3/5] COPY package.json /app: ------ failed to compute cache key: "/package.json" not found: not found
Let’s create missing files:
$ docker build -t your-image-name . [+] Building 1.9s (8/10) => [internal] load build definition from Dockerfile => => transferring dockerfile: 648B => [internal] load .dockerignore => => transferring context: 2B => [internal] load metadata for docker.io/library/python:3.8-slim => [auth] library/python:pull token for registry-1.docker.io => CANCELED [1/5] FROM docker.io/library/python:[email protected]:f4efb39d02df8cdc44485a0956ea62e63aab6bf2a1dcfb12fb5710bf95583e72 => => resolve docker.io/library/python:[email protected]:f4efb39d02df8cdc44485a0956ea62e63aab6bf2a1dcfb12fb5710bf95583e72 => => sha256:f4efb39d02df8cdc44485a0956ea62e63aab6bf2a1dcfb12fb5710bf95583e72 1.86kB / 1.86kB => [internal] load build context => => transferring context: 642B => CACHED [2/5] WORKDIR /app => ERROR [3/5] COPY requirements.txt /app ------ > [3/5] COPY requirements.txt /app: ------ failed to compute cache key: "/requirements.txt" not found: not found