1. Using Volumes to Develop Applications in Containers Flashcards
What can be said about the mutability of container images?
They are immutable — they don’t change.
How are container images defined?
They are defined declaratively using a text file called Dockerfile.
What does a Dockerfile contain?
A sequence of special instructions that inform Docker on how to create the container image.
What kind of details do Dockerfile instructions define?
- Which base image to use
- Which source files need to be copied from the host into the image
- The command that our container derived from the image will run
- And so on…
What process do we need to get an image built with an application inside it in Docker?
Docker’s image build process.
What happens when an image build is invoked using Docker’s CLI?
Docker reads and acts on the instructions in the Dockerfile, and makes use of any build artefacts such as compiled binaries to assemble the image that embodies the software application or service we want the container to run.
What is a Docker image?
It’s a template for the container.
Where does Docker’s image build process fit into the software development cycle?
Just before we get to the point where we need to run the application, and after we compile it.
What is the drawback of complex image definitions and how can this be alleviated?
Complex image definitions can take a significant amount of time to build and this can severely impact the productivity of a software developer. Our best bet for alleviating this is to develop inside the container where our code is destined to run.
What are the three implications of developing apps inside a container?
- Source code is part of the container’s filesystem
- Can run application and tests using the CLI
- Changes don’t persist on container deletion (ephemeral by nature)
What does Docker use to get around the ephemeral nature of data that’s located within a container’s file system?
Volumes.
What are Docker volumes?
A Docker volume is an area of persistent storage that is located outside of the container.
Where are Docker volumes located?
On the host that’s running Docker, on the network, or even cloud storage.
How does Docker use to work with volumes?
Volume plug-ins — a plug-in system for implementing storage solutions.
How does Docker provide access to data stored outside of the container?
It mounts the storage area into the container during the life of the container and unmounts the storage when it gets removed.
What are the three types of Docker volumes?
- Tmpfs Mount
- Named or Anonymous Volume
- Bind Mount
What are Tmpfs mounts?
Temporary areas of storage that mounts a storage location in the memory onto a destination in the container’s file system.
What is the primary use case of Tmpfs mounts?
Writing sensitive data to the container’s file system during its execution without ever touching a disk and becoming open to compromise.
What are named or anonymous volumes?
A designated area of storage that resides within a protected area under Docker’s control.
How can named or anonymous volumes be manipulated?
Using Docker CLI.
What do bind mounts allow us to do?
Mount an arbitrary directory on the host onto an arbitrary target location inside a container.
What can be said about the changes made inside a bind mount in terms of reflection?
Changes made in the bind mound from the container are reflected on the host and vice versa.
What is the explicit approach of creating a Docker volume?
Running the
volume subcomand in the Docker CLI along with the verb create
and specifying a name for the volume.
docker volume create code-volume
What is the explicit approach of creating a Docker volume?
Running the volume
subcomand in the Docker CLI along with the verb create
and specifying a name for the volume.
docker volume create code-volume
What is the explicit approach of creating a Docker volume?
Running the
volume subcomand in the Docker CLI along with the verb create
and specifying a name for the volume.
docker volume create code-volume
What is the implicit approach of creating a Docker volume?
Providing a --volume
option as part of the docker run
command. The argument specifies the volume name and the mount to use inside the container.
docker run --volume code-volume:/app
What happens when using the implicit approach to create a Docker volume if the volume already exists and what happens if it doesn’t?
It gets mounted if it exists and it gets created and mounted if it doesn’t.
What is the implicit approach of creating a Docker volume?
Providing a --volume
option as part of the docker run
command. The argument specifies the volume name and the mount to use inside the container.
docker run --volume code-volume:/app
What happens when using the implicit approach to create a Docker volume if the volume already exists and what happens if it doesn’t?
It gets mounted if it exists and it gets created and mounted if it doesn’t.
What Docker CLI sub-command can be used to list, inspect, and remove volumes? Why can this be done?
The sub-command volume
. This is because volumes are first-class citizens of Docker.
docker volume [ls/inspect/rm]
What are the advantages of using named volumes?
- They are Docker API objects, which means we can manage them easily
- They are a part of Docker’s internal data store, which means they are isolated from nefarious or accidental exposure or removal.
- We know where they reside, so they’re easy to identify and backup.
- Better performance when using Docker Desktop.
What are the disadvantages of using named volumes
- They are owned by the root user, which means you must run your container as the root user in order to write to the volume. (Bad for security, avoid.)
What can be said about running a container as the root user?
It is generally considered a bad practice for security reasons and should be avoided if at all possible.
What is a bind mount?
A location on the host mounted into a container.
How do you issue a bind mount when running a container?
By using the --volume
option to specify the absolute path to the file or directory on the host and also the absolute path in the container where the directory is to be mounted separated by a column.
docker run --volume /path/on/host:/path/in/container ...
What can be said about bind mounts in comparison to named volumes?
While named volumes impose a big restriction on us, bind mounts give us greater flexibility for data persistence.
What is the build context?
A location on the host that contains the application source and any other items that need to be embodied in the image, as well as a Dockerfile.
How do you specify what image to use in the Dockerfile?
By using the FROM
instruction.
FROM node:14
How do you specify the working directory in the Dockerfile?
By using the WORKDIR
instruction.
WORKDIR /app
How do you instruct the contents of the Dockerfile’s current directory to be copied across to the working directory inside the container?
By using the COPY
instruction and passing it two dots separated by spaces. The first one indicates the Dockerfile’s current directory and the second one specifies the working directory inside the container.
COPY . .
How do you instruct commands to be run once the app source is copied across to the working directory inside a container in the Dockerfile?
By using the RUN
instruction and giving it the commands to run, separated by &&
.
RUN npm install && npm install -g nodemon
How do you specify a port on which the containerised application listens for requests in the Dockerfile?
By using the EXPOSE
instruction and passing it the port number.
EXPOSE 3000
How do you specify the container’s default command (what gets executed) in the Dockerfile?
By using the CMD
instruction and and passing it each word of the full command as an array.
CMD [ "node", "src/index.js" ]
How do you build a Docker image?
By using the build
subcommand and passing it the name of the app using the -t
option as well as the path to the build context.
docker build -t myapp:1.0 .
ps. The dot (.) at the end specifies the current working directory.)
What happens when we invoke an image build?
Docker steps through each Dockerfile instruction until it gets to the end of the sequence, and we have a new image built for the application.
What are the two key concepts of handling dynamic changes in Docker?
- Watch for changes — edits to source code are automatically detected inside running container.
- Perform hot reload — process monitor performs a hot reload by restarting the application in the container.
What are the three key outcomes of mounting our source conte into the working directory using bind mount?
- Changes made to the source located on the host are reflected in the container via the bind mount volume.
- The hot reload utility automatically detects any changes to the source files and restarts the server.
- The changes can be tested to check they have implemented desired behaviour.
What is the issue with the file/folder permissions that needs handling when working with bind mounts?
The default user in the container is the root user, whose user ID and group ID don’t match the user developing the app. This mismatch can cause some unexpected behaviour.
eg.
If you create a file on the Docker host by using the touch command, you will se that the owner of this file is the local user.
However, when we run a container that uses a bind mount and use the touch command inside the container, the owner of the created file will be the container’s root user, which means that it’s owned by the root user on host. If you try to write to this file, you can’t. You don’t have the correct permissions.
How can we fix the permissions issue raised by using a bind mount?
By creating a new user group and adding it a new user whose ID matches the local user in the docker image using Linux command groupadd
and useradd
.
ps. This can be done in the Dockerfile like so:
RUN groupadd -r --gid 1000 user \ && useradd -r --uid 1000 -g user user
Having built an image from the docker file containing these lines, when we bind the host directory into the container, we also specify on the command line that the container must run as the user we’ve created.
docker run --volume $(pwd):/src --user user
What is the issue with the file/folder permissions that needs handling when working with bind mounts?
The default user in the container is the root user, whose user ID and group ID don’t match the user developing the app. This mismatch can cause some unexpected behaviour.
eg.
If you create a file on the Docker host by using the touch command, you will se that the owner of this file is the local user.
However, when we run a container that uses a bind mount and use the touch command inside the container, the owner of the created file will be the container’s root user, which means that it’s owned by the root user on host. If you try to write to this file, you can’t. You don’t have the correct permissions.
How do you instruct Dockerfile to add a new system user group for the container image?
By using the RUN
instruction to issue a Linux groupadd
command with the --system
option and specifying the group id using the --gid
option, as well ass specifying the user group name.
RUN groupadd --system --gid 1000 usergroup
How do you instruct Dockerfile to create a new system user add it to an existing user group for the container image?
By using the RUN
instruction to issue a Linux useradd
command with the --system
option, specifying the user ID using the --uid
option, and specifying the group ID or name using the --gid
option, as well as specifying in the new user’s name.
RUN ... \ && useradd --system --uid 1000 --gid usergroup user
How do you define dynamic variables in a Dockerfile which you can use the Command-Line to overwrite?
By using the ARG
instruction.
ARG UID=1000
ps. You can then use this variable elsewhere in the Dockerfile.
$UID
…and you can overwrite its value while running the docker build
command by passing it in using the --build-arg
option.
docker build --build-arg UID=1001 ...
How do you publish a port on the container to a port on the host while using the docker run
command?
By specifying the container’s port to be published and the host’s port for it to be published to using the --publish
option.
docker run --publish 3000:3000
What option to the docker run
command do we use to bind mount a volume?
--volume
How do you specify what command to run in combination with the ENTRYPOINT instruction specified in Dockerfile while running a container image on the CLI?
By specifying the command after the container image name specification.
docker run ..... todo:1.0 dev
ps. If the Dockerfile looks like:
ENTRYPOINT [“npm”, “run”]
CMD [“prod”]
~~~
```
…by default, it will run npm run prod
. When we pass it the dev
argument as seen above, it will instead run npm run dev
.