1. Introduction

As system administrators, we usually work with container images and use them to deploy our applications. In this article, we’ll delve into the steps involved in upgrading the Alpine image with bash.

Without further ado, let’s get into the nitty-gritty details of it.

2. What Is Alpine?

Generally, Alpine is an open-source, small, simple, and secure Linux distribution system. Predominantly, the Alpine Images are well-known for their smaller size and faster boot-in times.

For example, the size of the official Ubuntu Linux image is 3.6G, but the Alpine Linux image comes with an impressive size of 135MB. Furthermore, the containerized version of the Alpine Docker Image comes at just 5MB in size.

2.1. Accessing the Alpine Docker Image

For the sake of demonstration, let’s pull an OpenJDK Alpine image from the DockerHub repository using the docker pull command:

$ docker pull openjdk:8-jdk-alpine
8-jdk-alpine: Pulling from library/openjdk
...
... output truncated ...
...
Status: Downloaded newer image for openjdk:8-jdk-alpine

Also, we can retrieve the image information on the host machine using the docker images command:

$ docker images
REPOSITORY   TAG            IMAGE ID       CREATED        SIZE
openjdk      8-jdk-alpine   a3562aa0b991   3 years ago    105MB

Next, let’s spin an openjdk-alpine container using the image and try to access the bash through the tty (-t) and interactive (-i) sessions. As mentioned earlier, Alpine images are very light images that strip off all non-essential parts of the OS.

Hence, the base command line interpreter is available under /bin/sh, but the enhanced version of shell will not be there in Alpine images. The error indicates that the bash binary file is not accessible on the default path:

$ docker run -it a3562aa0b991 /bin/bash
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.
ERRO[0009] error waiting for container: context canceled 

However, the command line shell is accessible on /bin/sh:

$ docker run -it a3562aa0b991 /bin/sh
/ # 

3. Install bash the Alpine

Now, let’s try to install bash in the Alpine image and access the container through it. This can be accomplished in two ways: through the CLI or Dockerfile. We’ll showcase both options in the below sections.

3.1. Image Build Through CLI

Here, we’ll log in to the container with a basic command line interpreter (/bin/sh). Next, using the Alpine Package Keeper (apk), we can install bash into the container core utilities.

After successful installation, we can get the installed path of the bash with the help of which command:

$ docker run -i -t openjdk:8-jdk-alpine /bin/sh
/ # which bash
/ #
/ # apk add --no-cache bash
...
... output truncated ...
...
(5/5) Installing bash (4.4.19-r1)
Executing bash-4.4.19-r1.post-install
/ # which bash
/bin/bash

This installation forms a new layer on top of the existing openjdk-alpine container. The below snippets showcase the list of running and stopped containers on the host machine:

$ docker ps -a
CONTAINER ID   IMAGE          COMMAND     CREATED          STATUS                     PORTS     NAMES
daf51dcba91c   a3562aa0b991   "/bin/sh"   29 seconds ago   Exited (0) 7 seconds ago             happy_curie

Let’s use the docker commit command to turn this stopped container into an image:

$ docker commit daf51dcba91c openjdk:8-jdk-alpine-with-bash-cli-mode
sha256:be9564ccef2fa48c214d99eb06c044b606c67b0cb4ac1a1b713ae39018d640ce

$ docker images
REPOSITORY   TAG                               IMAGE ID       CREATED         SIZE
openjdk      8-jdk-alpine-with-bash-cli-mode   be9564ccef2f   6 seconds ago   110MB
openjdk      8-jdk-alpine                      a3562aa0b991   3 years ago     105MB

Let’s quickly spin a container with our custom-built Alpine image (openjdk:8-jdk-alpine-with-bash-cli-mode). Now, we can see that it directly takes us to the bash prompt:

$ docker run --rm -i -t openjdk:8-jdk-alpine-with-bash-cli-mode /bin/bash
bash-4.4#
bash-4.4# which bash
/bin/bash

3.2. Image Build Through Dockerfile

Alternatively, we can use Dockerfile to build the Alpine image with bash in a single step. Create a Dockerfile that contains a checklist of things that needs to build the image.

In our case, we are going to incorporate the bash inside the miniature Alpine image:

$ cat Dockerfile 
#Dockerfile to create a JDK Alpine Image with bash
FROM openjdk:8-jdk-alpine
MAINTAINER baeldung.com

# Update Alpine Linux Package Manager and Install the bash
RUN apk update && apk add bash

# Run the bash terminal on container startup
CMD /bin/bash

Let’s construct an image using the created Dockerfile on the same path. Each line in the Dockerfile creates an image layer. Finally, the openjdk:8-jdk-alpine-with-bash is successfully created:

$ docker build -t openjdk:8-jdk-alpine-with-bash .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM openjdk:8-jdk-alpine
 ---> a3562aa0b991
...
... output truncated ...
...
(5/5) Installing bash (4.4.19-r1)
Executing bash-4.4.19-r1.post-install
...
... output truncated ...
...
Successfully built 92440c815f97
Successfully tagged openjdk:8-jdk-alpine-with-bash

Using this image, let’s spin the container with bash as the command-line shell:

$ docker run --rm -i -t openjdk:8-jdk-alpine-with-bash /bin/bash
bash-4.4#
bash-4.4# which bash
/bin/bash

4. Conclusion

In summary, we’ve examined the Alpine images and their benefits. Then, we also described how to install and use bash on the Alpine Docker image.