diff --git a/README.md b/README.md
index 26253a8..579c328 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,13 @@
:information_source: This repo contains questions and exercises on various technical topics, sometimes related to DevOps and SRE
-:bar_chart: There are currently **2322** exercises and questions
+:bar_chart: There are currently **2371** exercises and questions
:books: To learn more about DevOps and SRE, check the resources in [devops-resources](https://github.com/bregman-arie/devops-resources) repository
:warning: You can use these for preparing for an interview but most of the questions and exercises don't represent an actual interview. Please read [FAQ page](faq.md) for more details
-:stop_sign: If you are interested in pursuing a career as DevOps engineer, learning some of the concepts mentioned here would be useful but you should know it's not about learning all the topics and technologies mentioned in this repository
-
-:busts_in_silhouette: Join our [DevOps community](https://www.facebook.com/groups/538897960007080) where we have discussions and share resources on DevOps
+:stop_sign: If you are interested in pursuing a career as DevOps engineer, learning some of the concepts mentioned here would be useful, but you should know it's not about learning all the topics and technologies mentioned in this repository
:pencil: You can add more exercises by submitting pull requests :) Read about contribution guidelines [here](CONTRIBUTING.md)
@@ -79,7 +77,7 @@
Perl |
- Kafka |
+ Kafka |
@@ -754,6 +752,12 @@ Yes, it's a operating-system-level virtualization, where the kernel is shared an
The introduction of virtual machines allowed companies to deploy multiple business applications on the same hardware while each application is separated from each other in secured way, where each is running on its own separate operating system.
+#### Virtual Machines
+
+
+Do we need virtual machines in the age of containers? Are they still relevant?
+
+
#### Python - OOP
@@ -4673,13 +4677,59 @@ https://idiallo.com/blog/c10k-2016
## Storage
-What types of storage formats are there?
+What types of storage are there?
* File
* Block
* Object
+
+Explain Object Storage
+
+- Data is divided to self-contained objects
+- Objects can contain metadata
+
+
+
+What are the pros and cons of object storage?
+
+Pros:
+ - Usually with object storage, you pay for what you use as opposed to other storage types where you pay for the storage space you allocate
+ - Scalable storage: Object storage mostly based on a model where what you use, is what you get and you can add storage as need
+Cons:
+ - Usually performs slower than other types of storage
+ - No granular modification: to change an object, you have re-create it
+
+
+
+What are some use cases for using object storage?
+
+
+
+Explain File Storage
+
+- File Storage used for storing data in files, in a hierarchical sturcture
+- Some of the devices for file storage: hard drive, flash drive, cloud-based file storage
+- Files usually organized in directories
+
+
+
+What are the pros and cons of File Storage?
+
+Pros:
+- Users have full control of their own files and can run variety of operations on the files: delete, read, write and move.
+- Security mechanism allows for users to have a better control at things such as file locking
+
+
+
+What are some examples of file storage?
+
+Local filesystem
+Dropbox
+Google Drive
+
+
What types of storage devices are there?
diff --git a/exercises/aws/README.md b/exercises/aws/README.md
index ac4d1c2..232e2a9 100644
--- a/exercises/aws/README.md
+++ b/exercises/aws/README.md
@@ -17,6 +17,46 @@
* [AWS Elastic Beanstalk](#exercises-aws-elastic-beanstalk)
* [AWS Misc](#exercises-aws-misc)
+## AWS Questions
+
+* [AWS Global Infrastructure](#questions-aws-global-infra)
+* [AWS IAM](#questions-aws-iam)
+* [AWS EC2](#questions-aws-ec2)
+ * [AMI](#questions-aws-ec2-ami)
+ * [EBS](#questions-aws-ec2-ebs)
+ * [Instance Store](#questions-aws-ec2-instance-store)
+ * [EFS](#questions-aws-ec2-efs)
+ * [Pricing Models](#questions-aws-ec2-pricing-models)
+ * [Launch Templates](#questions-aws-ec2-launch-templates)
+ * [ENI](#questions-aws-ec2-eni)
+ * [Placement Groups](#questions-aws-ec2-placement-groups)
+* [AWS Containers](#questions-aws-containers)
+ * [AWS ECS](#questions-aws-containers-ecs)
+ * [AWS Fargate](#questions-aws-containers-fargate)
+* [AWS S3](#questions-aws-s3)
+* [AWS Disaster Recovery](#questions-aws-disaster-recovery)
+* [AWS ELB](#questions-aws-elb)
+* [AWS Auto Scaling Group](#questions-aws-asg)
+* [AWS Security](#questions-aws-security)
+* [AWS Databases](#questions-aws-db)
+ * [AWS RDS](#questions-aws-db-rds)
+ * [AWS Aurora](#questions-aws-db-aurora)
+ * [AWS DynamoDB](#questions-aws-db-dynamodb)
+ * [AWS ElastiCache](#questions-aws-db-elasticache)
+ * [AWS RedShift](#questions-aws-db-redshift)
+* [AWS VPC](#questions-vpc)
+* [AWS DNS](#questions-aws-dns)
+* [AWS Monitoring and Logging](#questions-aws-monitoring-logging)
+* [AWS Billing and Support](#questions-aws-billing-support)
+* [AWS Automation](#questions-aws-automation)
+* [AWS Misc](#questions-aws-misc)
+* [AWS HA](#questions-aws-ha)
+* [AWS Production Operations and Migrations](#questions-aws-migrations)
+* [AWS Scenarios](#questions-aws-scenarios)
+* [AWS Architecture Design](#questions-aws-architecture-design)
+
+## Exercises
+
### IAM
@@ -120,43 +160,7 @@ Failover | Route 53 | [Exercise](route_53_failover.md) | [Solution](solutions/ro
| Budget Setup | Budget | [Exercise](budget_setup.md) | [Solution](solutions/budget_setup.md) | Easy |
| No Application :'( | Troubleshooting | [Exercise](no_application.md) | [Solution](solutions/no_application.md) | Easy |
-## AWS Self Assessment
-
-* [AWS Global Infrastructure](#questions-aws-global-infra)
-* [AWS IAM](#questions-aws-iam)
-* [AWS EC2](#questions-aws-ec2)
- * [AMI](#questions-aws-ec2-ami)
- * [EBS](#questions-aws-ec2-ebs)
- * [Instance Store](#questions-aws-ec2-instance-store)
- * [EFS](#questions-aws-ec2-efs)
- * [Pricing Models](#questions-aws-ec2-pricing-models)
- * [Launch Templates](#questions-aws-ec2-launch-templates)
- * [ENI](#questions-aws-ec2-eni)
- * [Placement Groups](#questions-aws-ec2-placement-groups)
-* [AWS Containers](#questions-aws-containers)
- * [AWS ECS](#questions-aws-containers-ecs)
- * [AWS Fargate](#questions-aws-containers-fargate)
-* [AWS S3](#questions-aws-s3)
-* [AWS Disaster Recovery](#questions-aws-disaster-recovery)
-* [AWS ELB](#questions-aws-elb)
-* [AWS Auto Scaling Group](#questions-aws-asg)
-* [AWS Security](#questions-aws-security)
-* [AWS Databases](#questions-aws-db)
- * [AWS RDS](#questions-aws-db-rds)
- * [AWS Aurora](#questions-aws-db-aurora)
- * [AWS DynamoDB](#questions-aws-db-dynamodb)
- * [AWS ElastiCache](#questions-aws-db-elasticache)
- * [AWS RedShift](#questions-aws-db-redshift)
-* [AWS VPC](#questions-vpc)
-* [AWS DNS](#questions-aws-dns)
-* [AWS Monitoring and Logging](#questions-aws-monitoring-logging)
-* [AWS Billing and Support](#questions-aws-billing-support)
-* [AWS Automation](#questions-aws-automation)
-* [AWS Misc](#questions-aws-misc)
-* [AWS HA](#questions-aws-ha)
-* [AWS Production Operations and Migrations](#questions-aws-migrations)
-* [AWS Scenarios](#questions-aws-scenarios)
-* [AWS Architecture Design](#questions-aws-architecture-design)
+## Questions
### Global Infrastructure
diff --git a/exercises/containers/README.md b/exercises/containers/README.md
index 93e5ada..5c5944b 100644
--- a/exercises/containers/README.md
+++ b/exercises/containers/README.md
@@ -1,37 +1,64 @@
# Containers
-## Containers Exercises
+## Exercises - Index
-|Name|Topic|Objective & Instructions|Solution|Comments|
-|--------|--------|------|----|----|
-|Running Containers|Basics|[Exercise](running_containers.md)|[Solution](solutions/running_containers.md)
-|Working with Images|Image|[Exercise](working_with_images.md)|[Solution](solutions/working_with_images.md)
-|Containerized Web Server|Applications|[Exercise](containerized_web_server.md)|[Solution](solutions/containerized_web_server.md)
-|Containerized Database|Applications|[Exercise](containerized_db.md)|[Solution](solutions/containerized_db.md)
-|Containerized Database with Persistent Storage|Applications|[Exercise](containerized_db_persistent_storage.md)|[Solution](solutions/containerized_db_persistent_storage.md)
-|My First Dockerfile|Dockerfile|[Exercise](write_dockerfile_run_container.md)|
-|Run, Forest, Run!|Restart Policies|[Exercise](run_forest_run.md)|[Solution](solutions/run_forest_run.md)
-|Layer by Layer|Image Layers|[Exercise](image_layers.md)|[Solution](solutions/image_layers.md)
-|Containerize an application | Containerization |[Exercise](containerize_app.md)|[Solution](solutions/containerize_app.md)
-|Multi-Stage Builds|Multi-Stage Builds|[Exercise](multi_stage_builds.md)|[Solution](solutions/multi_stage_builds.md)
+* [Running Containers](#exercises-running-containers)
+* [Images](#exercises-containers-images)
+* [Misc](#exercises-containers-misc)
-## Containers Self Assessment
+## Questions - Index
* [Containers 101](#questions-containers-101)
-* [OCI](#questions-oci)
-* [Images](#questions-images)
-* [Basic Commands](#questions-basic-commands)
+* [Common Commands](#questions-common-commands)
+* [Images](#questions-containers-images)
+ * [Tags](#questions-containers-images-tags)
+ * [Registry](#questions-containers-images-registry)
* [Storage](#questions-containers-storage)
-* [Dockerfile](#questions-dockerfile)
+* [Containerfile](#questions-containerfile)
* [Architecture](#questions-architecture)
* [Docker Architecture](#questions-docker-architecture)
* [Docker Compose](#questions-docker-compose)
-* [Docker Images](#questions-docker-images)
* [Networking](#questions-networking)
* [Docker Networking](#questions-docker-networking)
* [Security](#questions-security)
* [Docker In Production](#questions-docker-in-production)
* [Rootless Containers](#questions-rootless-containers)
+* [OCI](#questions-oci)
+* [Scenarios](#questions-scenarios)
+
+## Containers Exercises
+
+
+### Running Containers
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+|Running Containers|Basics|[Exercise](running_containers.md)|[Solution](solutions/running_containers.md)
+|Containerized Web Server|Applications|[Exercise](containerized_web_server.md)|[Solution](solutions/containerized_web_server.md)
+|Containerized Database|Applications|[Exercise](containerized_db.md)|[Solution](solutions/containerized_db.md)
+|Containerized Database with Persistent Storage|Applications|[Exercise](containerized_db_persistent_storage.md)|[Solution](solutions/containerized_db_persistent_storage.md)
+
+
+### Images
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+|Working with Images|Image|[Exercise](working_with_images.md)|[Solution](solutions/working_with_images.md)
+|Sharing Images (without a registry)|Images|[Exercise](sharing_images.md)|[Solution](solutions/sharing_images.md)
+|Creating images on the fly|Images|[Exercise](commit_image.md)|[Solution](solutions/commit_image.md)
+|My First Containerfile|Containerfile|[Exercise](write_containerfile_run_container.md)|
+
+
+### Misc
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+|Run, Forest, Run!|Restart Policies|[Exercise](run_forest_run.md)|[Solution](solutions/run_forest_run.md)
+|Layer by Layer|Image Layers|[Exercise](image_layers.md)|[Solution](solutions/image_layers.md)
+|Containerize an application | Containerization |[Exercise](containerize_app.md)|[Solution](solutions/containerize_app.md)
+|Multi-Stage Builds|Multi-Stage Builds|[Exercise](multi_stage_builds.md)|[Solution](solutions/multi_stage_builds.md)
+
+## Questions
### Containers 101
@@ -54,6 +81,14 @@ If to focus on OCI (Open Container Initiative) based containers, it offers the f
OCI provides a good [explanation](https://github.com/opencontainers/runtime-spec/blob/master/principles.md#the-5-principles-of-standard-containers): "Define a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in a format that is self-describing and portable, so that any compliant runtime can run it without extra dependencies, regardless of the underlying machine and the contents of the container."
+
+What is a container image?
+
+* An image of a container contains the application, its dependencies and the operating system where the application is executed.
+* It's a collection of read-only layers. These layers are loosely coupled
+ * Each layer is assembled out of one or more files
+
+
How are containers different from virtual machines (VMs)?
@@ -67,10 +102,6 @@ You can also think about it as containers are for OS-level virtualization while
* VMs portability considered to be limited when compared to containers
-
-Do we need virtual machines in the edge of containers? Are they still relevant?
-
-
In which scenarios would you use containers and in which you would prefer to use VMs?
@@ -86,8 +117,8 @@ You should choose containers when:
Describe the process of containerizing an application
-1. Write a Dockerfile that includes your app (including the commands to run it) and its dependencies
-2. Build the image using the Dockefile you wrote
+1. Write a Containerfile/Dockerfile that includes your app (including the commands to run it) and its dependencies
+2. Build the image using the Containerfile/Dockefile you wrote
3. You might want to push the image to a registry
4. Run the container using the image you've built
@@ -100,37 +131,109 @@ You should choose containers when:
* Isolation: Containers are isolated environments, usually changes made to the OS won't affect the containers and vice-versa
-
-### OCI
+
+### Commands Commands
+
+Note: I've used `Podman` in the answers, but other containers engines can be used as well (e.g. Docker)
-What is the OCI?
+How to run a container?
-OCI (Open Container Initiative) is an open governance established in 2015 to standardize container creation - mostly image format and runtime. At that time there were a number of parties involved and the most prominent one was Docker.
-
-Specifications published by OCI:
-
- - [image-spec](https://github.com/opencontainers/image-spec)
- - [runtime-spec](https://github.com/opencontainers/runtime-spec)
+`podman run ubuntu`
-Which operations OCI based containers must support?
+Why after running podman container run ubuntu
the output of podman container ls
is empty?
-Create, Kill, Delete, Start and Query State.
+Because the container immediately exits after running the ubuntu image. This is completely normal and expected as containers designed to run a service or a app and exit when they are done running it. To see the container you can run `podman ps -a`
+
+If you want the container to keep running, you can run a command like `sleep 100` which will run for 100 seconds or you can attach to terminal of the container with a command similar: `podman container run -it ubuntu /bin/bash`
+
+
+
+How to list all the containers on the local host?
+
+`podman container ls`
+
+
+
+How to attach your shell to a terminal of a running container?
+
+`podman container exec -it [container id/name] bash`
+
+This can be done in advance while running the container: `podman container run -it [image:tag] /bin/bash`
+
+
+
+True or False? You can remove a running container if it doesn't running anything
+
+False. You have to stop the container before removing it.
+
+
+
+How to stop and remove a container?
+
+`podman container stop && podman container rm `
+
+
+
+What happens when you run docker container run ubuntu
?
+
+1. Docker client posts the command to the API server running as part of the Docker daemon
+2. Docker daemon checks if a local image exists
+ 1. If it exists, it will use it
+ 2. If doesn't exists, it will go to the remote registry (Docker Hub by default) and pull the image locally
+3. containerd and runc are instructed (by the daemon) to create and start the container
+
+
+
+How to run a container in the background?
+
+With the -d flag. It will run in the background and will not attach it to the terminal.
+
+`docker container run -d httpd` or `podman container run -d httpd`
+
+
+
+If you'll run sleep 100
inside a container, will you see it when listing all the processes of the host on which the container runs? Why?
+
+
+
+True or False? If image httpd-service
has an entry point for running the httpd service then, the following will run the container and eventually the httpd service podman run httpd-service ls
+
+False. Running that command will override the entry point so the httpd service won't run and instead podman will run the `ls` command.
+
+
+
+True or False? Running podman restart CONTAINER_NAME
kills the main process inside the container and runs it again from scratch
+
+False. `podman restart` creates an entirely new container with the same ID while reusing the filesystem and state of the original container.
+
+
+
+You would like to run a web server inside a container but, be able to access it from the localhost. Demonstrate how to do that
+
+```
+podman run -d --name apache1 -p 8080:8080 registry.redhat.io/rhel8/httpd-24
+curl 127.0.0.1:8080
+```
+
+
+
+After running a container, it stopped. podman ps
shows nothing. How can you show its details?
+
+`podman ps -a` will shows also the details of a stopped container.
+
+
+
+How to list all the image tags for a given container image?
+
+`podman search --list-tags IMAGE_NAME`
### Images
-
-What is a container image?
-
-* An image of a container contains the application, its dependencies and the operating system where the application is executed.
-* It's a collection of read-only layers. These layers are loosely coupled
- * Each layer is assembled out of one or more files
-
-
Why container images are relatively small?
@@ -157,6 +260,7 @@ docker.io docker.io/rahulgadre/snake-game
How to list the container images on certain host?
+```
CONTAINER_BINARY=podman
$CONTAINER_BINARY images
```
@@ -173,35 +277,6 @@ $CONTAINER_BINARY pull rhel
```
-
-How the centralized location, where images are stored, is called?
-
-Registry
-
-
-
-A registry contains one or more ____
which in turn contain one or more ____
-
-A registry contains one or more repositories which in turn contain one or more images.
-
-
-
-How to find out which registry do you use by default from your environment?
-
-Depends on the containers technology you are using. For example, in case of Docker, it can be done with `docker info`
-
-```
-> docker info
-Registry: https://index.docker.io/v1
-```
-
-
-
-How to retrieve the latest ubuntu image?
-
-`podman image pull ubuntu:latest`
-
-
True or False? It's not possible to remove an image if a certain container is using it
@@ -273,6 +348,14 @@ One way to reach this situation is by building an image with exact same name and
In the case of Docker, you could use `docker history `
+
+What `podman commit` does?. When will you use it?
+
+Creates a new image from a running container. Users can apply extra changes to be saved in the new image version.
+
+Most of the time the user case for using `podman commit` would be to apply changes allowing to better debug the container. Not so much for creating a new image since commit adds additional overhead of potential logs and processes, not required for running the application in the container. This eventually makes images created by `podman commit` bigger due to the additional data stored there.
+
+
True or False? Multiple images can share layers
@@ -346,7 +429,7 @@ Look for "Cmd" or "Entrypoint" fields in the output of `docker image inspec
What is the role of cache in image builds?
-When you build an image for the first time, the different layers are being cached. So, while the first build of the image might take time, any other build of the same image (given that Dockerfile didn't change or the content used by the instructions) will be instant thanks to the caching mechanism used.
+When you build an image for the first time, the different layers are being cached. So, while the first build of the image might take time, any other build of the same image (given that Containerfile/Dockerfile didn't change or the content used by the instructions) will be instant thanks to the caching mechanism used.
In little bit more details, it works this way:
1. The first instruction (FROM) will check if base image already exists on the host before pulling it
@@ -357,6 +440,16 @@ In little bit more details, it works this way:
Note: in some cases (like COPY and ADD instructions) the instruction might stay the same but if the content of what being copied is changed then the cache is invalidated. The way this check is done is by comparing the checksum of each file that is being copied.
+
+How to remove an image from the host?
+
+`podman rmi IMAGE`
+
+It will fail if some containers are using it. You can then use `--force` flag for that but generally, it's better if you inspect the containers using the image before doing so.
+
+To delete all images: `podman rmi -a`
+
+
What ways are there to reduce container images size?
@@ -377,83 +470,287 @@ Cons:
* Push and pull can take more time (because no matching layers found on target)
-
-### Basic Commands
-
-How to list all the containers on a given host?
+You would like to share an image with another developer, but without using a registry. How would you do it?
-In the case of Docker, use: `docker container ls`
-Same with Podman: `podman container ls`
+```
+# On the local host
+podman save -o some_image.tar IMAGE
+rsync some_image.tar SOME_HOST
+
+# On the remote host
+podman load -i some_image.tar
+```
-How to run a container?
+True or False? Once a container is stopped and removed, its image removed as well from the host
-Docker: `docker container run ubuntu`
-Podman: `podman container run ubuntu`
+False. The image will still be available for use by potential containers in the future.
+To remove the container, run `podman rmi IMAGE`
-Why after running podman container run ubuntu
the output of podman container ls
is empty?
+How to view the instructions that were used to build image?
-Because the container immediately exits after running the ubuntu image. This is completely normal and expected as containers designed to run a service or a app and exit when they are done running it.
-
-If you want the container to keep running, you can run a command like `sleep 100` which will run for 100 seconds or you can attach to terminal of the container with a command similar: `podman container run -it ubuntu /bin/bash`
+`docker image history :`
-How to attach your shell to a terminal of a running container?
+How to find out which files were added to the container image filesystem?
-`podman container exec -it [container id/name] bash`
-
-This can be done in advance while running the container: `podman container run -it [image:tag] /bin/bash`
+`podman diff IMAGE_NAME`
-True or False? You can remove a running container if it doesn't running anything
+True or False? podman diff
works only on the container filesystem and not mounted files
-False. You have to stop the container before removing it.
+True. For mounted files you can use `podman inspec CONTAINER_NAMD/ID`
-How to stop and remove a container?
+How the centralized location, where images are stored, is called?
-`podman container stop && podman container rm `
+Registry
+
+
+
+#### Images - Registry
+
+
+What is a Registry?
+
+- A registry is a service which stores container images and allows users to pull specified images to run containers.
+- There are public registries (everyone can access them) and private (accessed only internally in the organization or specific network)
-What happens when you run docker container run ubuntu
?
+A registry contains one or more ____
which in turn contain one or more ____
-1. Docker client posts the command to the API server running as part of the Docker daemon
-2. Docker daemon checks if a local image exists
- 1. If it exists, it will use it
- 2. If doesn't exists, it will go to the remote registry (Docker Hub by default) and pull the image locally
-3. containerd and runc are instructed (by the daemon) to create and start the container
+A registry contains one or more repositories which in turn contain one or more images.
-How to run a container in the background?
+How to find out which registry do you use by default from your environment?
-With the -d flag. It will run in the background and will not attach it to the terminal.
+Depends on the containers technology you are using. For example, in case of Docker, it can be done with `docker info`
-`docker container run -d httpd` or `podman container run -d httpd`
+```
+> docker info
+Registry: https://index.docker.io/v1
+```
-If you'll run sleep 100
inside a container, will you see it when listing all the processes of the host on which the container runs? Why?
+How to configure registries with the containers engine you are using?
+
+For podman, registries can be configured in `/etc/containers/registries.conf` this way:
+
+```
+[registries.search]
+registries = ["quay.io"]
+```
-True or False? If image httpd-service
has an entry point for running the httpd service then, the following will run the container and eventually the httpd service podman run httpd-service ls
+How to retrieve the latest ubuntu image?
-False. Running that command will override the entry point so the httpd service won't run and instead podman will run the `ls` command.
+`podman image pull ubuntu:latest`
-True or False? Running podman restart CONTAINER_NAME
kills the main process inside the container and runs it again from scratch
+How to push an image to a registry?
-False. `podman restart` creates an entirely new container with the same ID while reusing the filesystem and state of the original container.
+`podman push IMAGE`
+
+You can specify a specific registry: `podman push IMAGE REGISTRY_ADDRESS`
+
+
+
+What are some best practices in regards to Container Images?
+
+- Use tags. Using `latest` is quite common (which can mean latest build or latest release)
+ - tag like `3.1` can be used to reference the latest release/tag of the image like `3.1.6`
+- Don't use `commit` for creating new official images as they include the overhead of logs and processes and usually end up with bigger images
+- For sharing the image, use a registry (either a public or a private one, depends on your needs)
+
+
+
+What ways are there for creating new images?
+
+1. Create a Containerfile/Dockerfile and build an image out of it
+2. Using `podman commit` on a running container after making changes to it
+
+
+
+#### Images - Tags
+
+
+What are image tags? Why is it recommended to use tags when supporting multiple releases/versions of a project?
+
+Image tags are used to distinguish between multiple versions of the same software or project. Let's say you developed a project called "FluffyUnicorn" and the current release is `1.0`. You are about to release `1.1` but you still want to keep `1.0` as stable release for anyone who is interested in it. What would you do? If your answer is create another, separate new image, then you probably want to rethink the idea and just create a new image tag for the new release.
+
+In addition, it's important to note that container registries support tags. So when pulling an image, you can specify a specific tag of that image.
+
+
+
+How to tag an image?
+
+`podman tag IMAGE:TAG`
+
+for example: `podman tag FluffyUnicorn:latest`
+
+
+
+True or False? Once created, it's impossible to remove a tag for a certain image
+
+False. You can run `podman rmi IMAGE:TAG`.
+
+
+
+True or False? Multiple tags can reference the same image
+
+True.
+
+
+### Containerfile
+
+
+What is a Containerfile/Dockerfile?
+
+Different container engines (e.g. Docker, Podman) can build images automatically by reading the instructions from a Containerfile/Dockerfile. A Containerfile/Dockerfile is a text file that contains all the instructions for building an image which containers can use.
+
+
+
+What instruction exists in every Containerfile/Dockefile and what does it do?
+
+In every Containerfile/Dockerfile, you can find the instruction `FROM ` which is also the first instruction (at least most of the time. You can put ARG before).
+It specifies the base layer of the image to be used. Every other instruction is a layer on top of that base image.
+
+
+
+List five different instructions that are available for use in a Containerfile/Dockerfile
+
+ * WORKDIR: sets the working directory inside the image filesystems for all the instructions following it
+ * EXPOSE: exposes the specified port (it doesn't adds a new layer, rather documented as image metadata)
+ * ENTRYPOINT: specifies the startup commands to run when a container is started from the image
+ * ENV: sets an environment variable to the given value
+ * USER: sets the user (and optionally the user group) to use while running the image
+
+
+
+What are some of the best practices regarding Containerfiles/Dockerfiles that you are following?
+
+ * Include only the packages you are going to use. Nothing else.
+ * Specify a tag in FROM instruction. Not using a tag means you'll always pull the latest, which changes over time and might result in unexpected result.
+ * Do not use environment variables to share secrets
+ * Use images from official repositories
+ * Keep images small! - you want them only to include what is required for the application to run successfully. Nothing else.
+ * If are using the apt package manager, you might want to use 'no-install-recommends' with `apt-get install` to install only main dependencies (instead of suggested, recommended packages)
+
+
+
+What is the "build context"?
+
+[Docker docs](https://docs.docker.com/engine/reference/commandline/build): "A build’s context is the set of files located in the specified PATH or URL"
+
+
+
+What is the difference between ADD and COPY in Containerfile/Dockerfile?
+
+COPY takes in a source and destination. It lets you copy in a file or directory from the build context into the Docker image itself.
+ADD lets you do the same, but it also supports two other sources. You can use a URL instead of a file or directory from the build context. In addition, you can extract a tar file from the source directly into the destination.
+
+Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of files from build context into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious.
+
+
+
+What is the difference between CMD and RUN in Containerfile/Dockerfile?
+
+RUN lets you execute commands inside of your Docker image. These commands get executed once at build time and get written into your Docker image as a new layer.
+CMD is the command the container executes by default when you launch the built image. A Containerfile/Dockerfile can only have one CMD.
+You could say that CMD is a Docker run-time operation, meaning it’s not something that gets executed at build time. It happens when you run an image. A running image is called a container.
+
+
+
+How to create a new image using a Containerfile/Dockerfile?
+
+The following command is executed from within the directory where Dockefile resides:
+
+`docker image build -t some_app:latest .`
+`podman image build -t some_app:latest .`
+
+
+
+Do you perform any checks or testing on your Containerfiles/Dockerfiles?
+
+One option is to use [hadolint](https://github.com/hadolint/hadolint) project which is a linter based on Containerfile/Dockerfile best practices.
+
+
+
+Which instructions in Containerfile/Dockerfile create new layers?
+
+Instructions such as FROM, COPY and RUN, create new image layers instead of just adding metadata.
+
+
+
+Which instructions in Containerfile/Dockerfile create image metadata and don't create new layers?
+
+Instructions such as ENTRYPOINT, ENV, EXPOSE, create image metadata and they don't create new layers.
+
+
+
+Is it possible to identify which instruction create a new layer from the output of podman image history
?
+
+
+
+True or False? Each Containerfile instruction runs in an independent container using an image built from every previous layer/entry
+
+True
+
+
+
+What's the difference between these two forms:
+
+```
+ENTRYPOINT ["cmd", "param0", "param1"]
+CMD ["param0"]
+
+ENTRYPOINT cmd param0 param1
+CMD param0
+```
+
+
+The first form is also referred as "Exec form" and the second one is referred as "Shell form".
+The second one (Shell form) wraps the commands in `/bin/sh -c` hence creates a shell process for it.
+
+While using either Exec form or Shell form might be fine, it's the mixing that can lead to unexpected results.
+Consider:
+
+```
+ENTRYPOINT ["ls"]
+CMD /tmp
+```
+
+That would results in running `ls /bin/sh -c /tmp`
+
+
+
+Containerfile/Dockerfile can contain more than one ENTRYPOINT instruction and one CMD instruction
+
+True but in case of ENTRYPOINT and CMD only the last instruction takes effect.
+
+
+
+What happens when CMD instruction is defined but not an ENTRYPOINT instruction in a Containerfile/Dockerfile?
+
+The ENTRYPOINT from the base image is being used in such case.
+
+
+
+In the case of running podman run -it IMAGE ls
the ls
overrides the ___
instruction
+
+CMD
@@ -505,96 +802,7 @@ sudo restorecon -Rv /tmp/dir_on_the_host
```
-
-### Dockerfile
-
-
-What is a Dockerfile?
-
-Different container engines (e.g. Docker, Podman) can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text file that contains all the instructions for building an image which containers can use.
-
-
-
-What is the instruction in all Dockefiles and what does it mean?
-
-The first instruction is `FROM `
-It specifies the base layer of the image to be used. Every other instruction is a layer on top of that base image.
-
-
-
-List five different instructions that are available for use in a Dockerfile
-
- * WORKDIR: sets the working directory inside the image filesystems for all the instructions following it
- * EXPOSE: exposes the specified port (it doesn't adds a new layer, rather documented as image metadata)
- * ENTRYPOINT: specifies the startup commands to run when a container is started from the image
- * ENV: sets an environment variable to the given value
- * USER: sets the user (and optionally the user group) to use while running the image
-
-
-
-What are some of the best practices regarding container images and Dockerfiles that you are following?
-
- * Include only the packages you are going to use. Nothing else.
- * Specify a tag in FROM instruction. Not using a tag means you'll always pull the latest, which changes over time and might result in unexpected result.
- * Do not use environment variables to share secrets
- * Use images from official repositories
- * Keep images small! - you want them only to include what is required for the application to run successfully. Nothing else.
- * If are using the apt package manager, you might use 'no-install-recommends' with `apt-get install` to install only main dependencies (instead of suggested, recommended packages)
-
-
-
-What is the "build context"?
-
-[Docker docs](https://docs.docker.com/engine/reference/commandline/build): "A build’s context is the set of files located in the specified PATH or URL"
-
-
-
-What is the difference between ADD and COPY in Dockerfile?
-
-COPY takes in a source and destination. It lets you copy in a file or directory from the build context into the Docker image itself.
-ADD lets you do the same, but it also supports two other sources. You can use a URL instead of a file or directory from the build context. In addition, you can extract a tar file from the source directly into the destination.
-
-Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of files from build context into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious.
-
-
-
-What is the difference between CMD and RUN in Dockerfile?
-
-RUN lets you execute commands inside of your Docker image. These commands get executed once at build time and get written into your Docker image as a new layer.
-CMD is the command the container executes by default when you launch the built image. A Dockerfile can only have one CMD.
-You could say that CMD is a Docker run-time operation, meaning it’s not something that gets executed at build time. It happens when you run an image. A running image is called a container.
-
-
-
-How to create a new image using a Dockerfile?
-
-The following command is executed from within the directory where Dockefile resides:
-
-`docker image build -t some_app:latest .`
-`podman image build -t some_app:latest .`
-
-
-
-Do you perform any checks or testing on your Dockerfiles?
-
-One option is to use [hadolint](https://github.com/hadolint/hadolint) project which is a linter based on Dockerfile best practices.
-
-
-
-Which instructions in Dockerfile create new layers?
-
-Instructions such as FROM, COPY and RUN, create new image layers instead of just adding metadata.
-
-
-
-Which instructions in Dockerfile create image metadata and don't create new layers?
-
-Instructions such as ENTRYPOINT, ENV, EXPOSE, create image metadata and they don't create new layers.
-
-
-
-Is it possible to identify which instruction create a new layer from the output of docker image history
?
-
+
### Architecture
@@ -781,12 +989,6 @@ shim is the process that becomes the container's parent when runc process exists
- Making sure the container doesn't terminate if the daemon is being restarted. It does so by keeping the stdout and stdin open
-
-What `podman commit` does?. When will you use it?
-
-Create a new image from a container’s changes
-
-
How would you transfer data from one container into another?
@@ -795,18 +997,6 @@ Create a new image from a container’s changes
What happens to data of the container when a container exists?
-
-Explain what each of the following commands do:
-
- * docker run
- * docker rm
- * docker ps
- * docker pull
- * docker build
- * docker commit
-
-
-
How do you remove old, non running, containers?
@@ -832,7 +1022,7 @@ Via the local socket at `/var/run/docker.sock`
Explain image layers
-A Docker image is built up from a series of layers. Each layer represents an instruction in the image’s Dockerfile. Each layer except the very last one is read-only.
+A Docker image is built up from a series of layers. Each layer represents an instruction in the image’s Containerfile/Dockerfile. Each layer except the very last one is read-only.
Each layer is only a set of differences from the layer before it. The layers are stacked on top of each other. When you create a new container, you add a new writable layer on top of the underlying layers. This layer is often called the “container layer”. All changes made to the running container, such as writing new files, modifying existing files, and deleting files, are written to this thin writable container layer.
The major difference between a container and an image is the top writable layer. All writes to the container that add new or modify existing data are stored in this writable layer. When the container is deleted, the writable layer is also deleted. The underlying image remains unchanged.
Because each container has its own writable container layer, and all changes are stored in this container layer, multiple containers can share access to the same underlying image and yet have their own data state.
@@ -873,42 +1063,12 @@ In general, it's useful for running applications which composed out of several d
* Run `docker-compose up` to run the services
-
-### Docker Images
-
-
-What is Docker Hub?
-
-One of the most common registries for retrieving images.
-
-
-
-How to push an image to Docker Hub?
-
-`docker image push [username]/[image name]:[tag]`
-
-For example:
-
-`docker image mario/web_app:latest`
-
-
-
-What is the difference between Docker Hub and Docker cloud?
-
-Docker Hub is a native Docker registry service which allows you to run pull
-and push commands to install and deploy Docker images from the Docker Hub.
-
-Docker Cloud is built on top of the Docker Hub so Docker Cloud provides
-you with more options/features compared to Docker Hub. One example is
-Swarm management which means you can create new swarms in Docker Cloud.
-
-
Explain Multi-stage builds
Multi-stages builds allow you to produce smaller container images by splitting the build process into multiple stages.
-As an example, imagine you have one Dockerfile where you first build the application and then run it. The whole build process of the application might be using packages and libraries you don't really need for running the application later. Moreover, the build process might produce different artifacts which not all are needed for running the application.
+As an example, imagine you have one Containerfile/Dockerfile where you first build the application and then run it. The whole build process of the application might be using packages and libraries you don't really need for running the application later. Moreover, the build process might produce different artifacts which not all are needed for running the application.
How do you deal with that? Sure, one option is to add more instructions to remove all the unnecessary stuff but, there are a couple of issues with this approach:
1. You need to know what to remove exactly and that might be not as straightforward as you think
@@ -1078,3 +1238,42 @@ Networking is usually managed by Slirp in rootless containers. Slirp creates a t
New drivers were created to allow creating filesystems in a user namespaces. Drivers like the FUSE-OverlayFS.
+
+
+### OCI
+
+
+What is the OCI?
+
+OCI (Open Container Initiative) is an open governance established in 2015 to standardize container creation - mostly image format and runtime. At that time there were a number of parties involved and the most prominent one was Docker.
+
+Specifications published by OCI:
+
+ - [image-spec](https://github.com/opencontainers/image-spec)
+ - [runtime-spec](https://github.com/opencontainers/runtime-spec)
+
+
+
+Which operations OCI based containers must support?
+
+Create, Kill, Delete, Start and Query State.
+
+
+
+### Scenarios
+
+
+There is a running container that has a certain issue. You would like to share an image of that container with your team members, with certain environment variables set for debugging purposes. How would you do it?
+
+`podman commit` can be a good choice for that. You can create a new image of the running container (with the issue) and share that new image with your team members.
+
+What you probably want to avoid using:
+ - Using something as `podman save/load` as it applies on an image, not a running container (so you'll share the image but the issue might not be reproduced when your team members run a container using it)
+ - Modifying Containerfile/Dockerfile as you don't really want to add environment variables meant for debugging to the source from which you usually build images
+
+
+
+You and your team work on the same project, but different versions of it. For each version, the team creates a new, separate image. What would you suggest the team to change in such case?
+
+Use tags. You can distinguish between different releases of a project using image tags. There is no need to create an entire separate image for version/release of a project.
+
diff --git a/exercises/containers/commit_image.md b/exercises/containers/commit_image.md
new file mode 100644
index 0000000..0c2381b
--- /dev/null
+++ b/exercises/containers/commit_image.md
@@ -0,0 +1,36 @@
+# Create Images on The Fly
+
+## Requirements
+
+Have at least one image locally (run `podman image ls` to confirm).
+If you don't have images locally, run simply `podman pull nginx:alpine`.
+
+## Objectives
+
+1. Run a container using a web server image (e.g. httpd, nginx, ...)
+ - Bind container's port 80 to local port 80
+ - Run it in detached mode
+ - Name should nginx_container
+2. Verify the web server runs and accessible
+3. Create an HTML file with the following content and copy it to the container to the container to path where it will be accessed as an index file
+
+```
+
+
+It's a me
+
+
+Mario
+
+```
+
+4. Create an image out of the running container and call it "nginx_mario"
+5. Tag the container with "mario" tag
+6. Remove the original container (container_nginx) and verify it was removed
+7. Create a new container out of the image you've created (the same way as the original container)
+8. Run `curl 127.0.0.1:80`. What do you see?
+9. Run `podman diff` on the new image. Explain the output
+
+## Solution
+
+Click [here to view the solution](solutions/commit_image.md)
diff --git a/exercises/containers/containerized_web_server.md b/exercises/containers/containerized_web_server.md
index 3311cba..852c80b 100644
--- a/exercises/containers/containerized_web_server.md
+++ b/exercises/containers/containerized_web_server.md
@@ -3,5 +3,6 @@
1. Run a containerized web server in the background and bind its port (8080) to a local port
2. Verify the port (8080) is bound
3. Reach the webserver from your local host
+4. Now run the same web application but bound it to the local port 8080
Click [here for the solution](solutions/containerized_web_server.md)
diff --git a/exercises/containers/sharing_images.md b/exercises/containers/sharing_images.md
new file mode 100644
index 0000000..726ef41
--- /dev/null
+++ b/exercises/containers/sharing_images.md
@@ -0,0 +1,18 @@
+# Sharing Images
+
+## Requirements
+
+Have at least one image locally (run `podman image ls` to confirm).
+If you don't have images locally, run simply `podman pull httpd`.
+
+## Objectives
+
+1. Choose an image and create an archive out of it
+2. Check the archive size. Is it different than the image size? If yes, what's the difference? If not, why?
+3. Copy the generated archive to a remote host
+4. Load the image
+5. Verify it was loaded and exists on the remote host
+
+## Solution
+
+Click [here to view the solution](solutions/sharing_images.md)
diff --git a/exercises/containers/solutions/commit_image.md b/exercises/containers/solutions/commit_image.md
new file mode 100644
index 0000000..58c19ba
--- /dev/null
+++ b/exercises/containers/solutions/commit_image.md
@@ -0,0 +1,107 @@
+# Create Images on The Fly
+
+## Requirements
+
+Have at least one image locally (run `podman image ls` to confirm).
+If you don't have images locally, run simply `podman pull nginx:alpine`.
+
+## Objectives
+
+1. Run a container using a web server image (e.g. httpd, nginx, ...)
+ - Bind container's port 80 to local port 80
+ - Run it in detached mode
+ - Name should nginx_container
+2. Verify the web server runs and accessible
+3. Create an HTML file with the following content and copy it to the container to the container to path where it will be accessed as an index file
+
+```
+
+
+It's a me
+
+
+Mario
+
+```
+
+4. Create an image out of the running container and call it "nginx_mario"
+5. Tag the container with "mario" tag
+6. Remove the original container (container_nginx) and verify it was removed
+7. Create a new container out of the image you've created (the same way as the original container)
+8. Run `curl 127.0.0.1:80`. What do you see?
+9. Run `podman diff` on the new image. Explain the output
+
+## Solution
+
+```
+# Run the container
+podman run --name nginx_container -d -p 80:80 nginx:alpine
+
+# Verify web server is running
+curl 127.0.0.1:80
+ #
+ #
+ #
+ # Welcome to nginx!
+
+# Create index.html file
+cat <>index.html
+
+
+It's a me
+
+
+Mario
+
+EOT
+
+# Copy index.html to the container
+podman cp index.html nginx_container:/usr/share/nginx/html/index.html
+
+# Create a new image out of the running container
+podman commit nginx_container nginx_mario
+
+# Tag the image
+podman image ls
+# localhost/nginx_mario latest dc7ed2343521 52 seconds ago 25 MB
+podman tag dc7ed2343521 mario
+
+# Remove the container
+podman stop nginx_container
+podman rm nginx_container
+podman ps -a # no container 'nginx_container'
+
+# Create a container out of the image
+podman run -d -p 80:80 nginx_mario
+
+# Check the container created from the new image
+curl 127.0.0.1:80
+#
+#
+#It's a me
+#
+#
+#Mario
+#
+
+# Run diff
+podman diff nginx_mario
+
+C /etc
+C /etc/nginx/conf.d
+C /etc/nginx/conf.d/default.conf
+A /run/nginx.pid
+C /usr/share/nginx/html
+C /usr/share/nginx/html/index.html
+C /var/cache/nginx
+C /var
+C /var/cache
+A /var/cache/nginx/client_temp
+A /var/cache/nginx/fastcgi_temp
+A /var/cache/nginx/proxy_temp
+A /var/cache/nginx/scgi_temp
+A /var/cache/nginx/uwsgi_temp
+
+# We've set new index.html which explains why it's changed (C)
+# We also created the image while the web server is running, which explains all the files created under /var
+```
diff --git a/exercises/containers/solutions/containerized_web_server.md b/exercises/containers/solutions/containerized_web_server.md
index f596445..ed89648 100644
--- a/exercises/containers/solutions/containerized_web_server.md
+++ b/exercises/containers/solutions/containerized_web_server.md
@@ -3,6 +3,7 @@
1. Run a containerized web server in the background and bind its port (8080) to a local port
2. Verify the port (8080) is bound
3. Reach the webserver from your local host
+4. Now run the same web application but bound it to the local port 8080
## Solution
@@ -18,4 +19,6 @@ $ curl http://0.0.0.0:41203 # use the port from the output of the previous comma
Test Page for the HTTP Server on Red Hat Enterprise Linux
+
+$ podman run -d -p 8080:8080 httpd
```
diff --git a/exercises/containers/solutions/sharing_images.md b/exercises/containers/solutions/sharing_images.md
new file mode 100644
index 0000000..4054c38
--- /dev/null
+++ b/exercises/containers/solutions/sharing_images.md
@@ -0,0 +1,35 @@
+# Sharing Images
+
+## Requirements
+
+Have at least one image locally (run `podman image ls` to confirm).
+If you don't have images locally, run simply `podman pull httpd`.
+
+## Objectives
+
+1. Choose an image and create an archive out of it
+2. Check the archive size. Is it different than the image size? If yes, what's the difference? If not, why?
+3. Copy the generated archive to a remote host
+4. Load the image
+5. Verify it was loaded and exists on the remote host
+
+## Solution
+
+```
+# Save image as an archive
+podman save -o httpd.tar httpd
+
+# Check archive and image sizes
+du -sh httpd.tar # output: 143MB
+podman image ls | grep httpd # output: 149MB
+# The archive is obviously smaller than the image itself (6MB difference)
+
+# Copy the archive to a remote host
+rsync -azc httpd.tar USER@REMOTE_HOST_FQDN:/tmp/
+
+# Load the image
+podman load -i /tmp/httpd.tar
+
+# Verify it exists on the system after loading
+podman image ls
+```
diff --git a/exercises/containers/write_containerfile_run_container.md b/exercises/containers/write_containerfile_run_container.md
new file mode 100644
index 0000000..7b31a14
--- /dev/null
+++ b/exercises/containers/write_containerfile_run_container.md
@@ -0,0 +1,11 @@
+# Write a Containerfile and run a container
+
+## Objectives
+
+1. Create a Docker image:
+ * Use centos or ubuntu as the base image
+ * Install apache web server
+ * Deploy any web application you want
+ * Add https support (using HAProxy as reverse-proxy)
+2. Once you wrote the Containerfile and created an image, run the container and test the application. Describe how did you test it and provide output
+3. Describe one or more weakness of your Containerfile. Is it ready to be used in production?
diff --git a/exercises/containers/write_dockerfile_run_container.md b/exercises/containers/write_dockerfile_run_container.md
deleted file mode 100644
index 8627a20..0000000
--- a/exercises/containers/write_dockerfile_run_container.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Write a Dockerfile and run a container
-
-Your task is as follows:
-
-1. Create a Docker image:
- * Use centos or ubuntu as the base image
- * Install apache web server
- * Deploy any web application you want
- * Add https support (using HAProxy as reverse-proxy)
-2. Once you wrote the Dockerfile and created an image, run the container and test the application. Describe how did you test it and provide output
-3. Describe one or more weakness of your Dockerfile. Is it ready to be used in production?
diff --git a/exercises/linux/README.md b/exercises/linux/README.md
index 9c5b35f..4cff3aa 100644
--- a/exercises/linux/README.md
+++ b/exercises/linux/README.md
@@ -12,7 +12,8 @@ A completely free application for testing your knowledge on Linux
* [Linux I/O Redirection](#questions-linux-redirection)
* [Linux Filesystem Hierarchy Standard](#questions-linux-fhs)
* [Linux Permissions](#questions-linux-permissions)
-* [Linux Systemd](#questions-linux-fhs)
+* [Linux Scenarios](#questions-linux-scenarios)
+* [Linux Systemd](#questions-linux-systemd)
* [Linux Troubleshooting and Debugging](#questions-linux-troubleshooting)
* [Linux kernel](#questions-linux-kernel)
* [Linux SSH](#questions-linux-ssh)
@@ -414,6 +415,27 @@ True
Using `sudo setfacl -m u::rx /usr/bin/chmod` will set the execute permissions on `chmod` for all the users. Post this, the `chmod` binary can be used as usual.
+
+### Scenarios
+
+
+You would like to copy a file to a remote Linux host. How would you do?
+
+There are multiple ways to transfer files between hosts. Personal opinion: use `rsync`
+
+
+
+How to generate a random string?
+
+One way is to run the following: `cat /proc/sys/kernel/random/uuid`
+
+
+
+How to generate a random string of 7 characters?
+
+`mkpasswd -l 7`
+
+
### Systemd
@@ -2056,12 +2078,6 @@ MemAvailable - The amount of available memory for new workloads (without pushing
### Misc
-
-How to generate a random string?
-
-One way is to run the following: `cat /proc/sys/kernel/random/uuid`
-
-
What is a Linux distribution?