Content:
**Ref: https://github.com/sidpalas/devops-directive-docker-course/tree/main/04-using-3rd-party-containers
01 - History and Motivation
02 - Technology Overview
03 - Installation and Set Up
04 - Using 3rd Party Containers
05 - Example Web Application
06 - Building Container Images
07 - Container Registries
08 - Running Containers
09 - Container Security
10 - Interacting with Docker Objects
11 - Development Workflows
12 - Deploying Containers
Architecture of docker
Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and deploy it as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code
Containers work a little like VMs, but in a far more specific and granular way. They isolate a single application and its dependencies—all of the external software libraries the app requires to run—both from the underlying operating system and from other containers. All of the containerized apps share a single, common operating system (either Linux or Windows), but they are compartmentalized from one another and from the system at large.
To check docker
systemctl status docker (active) : in docker from system it will take binary format and interact with docker diamon and displays the related data.
In simple words:
"Container is a lightweight,standalone,executable,package of software that includes everything needs to run an application"
OCI:OPEN CONTAINER INTIATIVE:
"Its an open governance structure for the express purpose of creating open industry standards around container formats and runtime"
:- Runtime specification
:- Image Specification
:- Distribution specification
======================================================================
# Create a container from the ubuntu image (with a name and WITHOUT the --rm flag)
docker run -it --name my-ubuntu-container ubuntu:22.04
# Install & use ping
apt update
apt install iputils-ping --yes
ping google.com -c 1
exit
# List all containers
docker container ps -a | grep my-ubuntu-container
docker container inspect my-ubuntu-container
# Restart the container and attach to running shell
docker start my-ubuntu-container
docker attach my-ubuntu-container
# Test ping
ping google.com -c 1 # It should now succeed! 🎉
exit
======================================================================
Let's experiment with how creating some data within a container at runtime behaves!
# Create a container from the ubuntu image
docker run -it --rm ubuntu:22.04
# Make a directory and store a file in it
mkdir my-data
echo "Hello from the container!" > /my-data/hello.txt
# Confirm the file exists
cat my-data/hello.txt
exit
If we then create a new container, (as expected) the file does not exist!
To solve code persistent we are using the volumes
i. Volume Mounts
We can use volumes and mounts to safely persist the data.
# create a named volume
docker volume create my-volume
# Create a container and mount the volume into the container filesystem
docker run -it --rm --mount source=my-volume,destination=/my-data/ ubuntu:22.04
# There is a similar (but shorter) syntax using -v which accomplishes the same
docker run -it --rm -v my-volume:/my-data ubuntu:22.04
# Now we can create and store the file into the location we mounted the volume
echo "Hello from the container!" > /my-data/hello.txt
cat my-data/hello.txt
exit
We can now create a new container and mount the existing volume to confirm the file persisted:
# Create a new container and mount the volume into the container filesystem
docker run -it --rm --mount source=my-volume,destination=/my-data/ ubuntu:22.04
cat my-data/hello.txt # This time it succeeds!
exit
Where is this data located? On linux it would be at /var/lib/docker/volumes... but remember, on docker desktop, Docker runs a linux virtual machine.
# Create a container that can access the Docker Linux VM
# Pinning to the image hash ensures it is this SPECIFIC image and not an updated one helps minimize the potential of a supply chain attack
docker run -it --rm --privileged --pid=host justincormack/nsenter1@sha256:5af0be5e42ebd55eea2c593e4622f810065c3f45bb805eaacf43f08f3d06ffd8
# Navigate to the volume inside the VM at:
ls /var/lib/docker/volumes/my-volume/_data
cat /var/lib/docker/volumes/my-volume/_data/hello.txt # Woohoo! we found our data!
----------------------------------------------------------------------------------------------------------------
ii. Bind Mounts
Alternatively, we can mount a directory from the host system using a bind mount:
# Create a container that mounts a directory from the host filesystem into the container
docker run -it --rm --mount type=bind,source="${PWD}"/my-data,destination=/my-data ubuntu:22.04
# Again, there is a similar (but shorter) syntax using -v which accomplishes the same
docker run -it --rm -v ${PWD}/my-data:/my-data ubuntu:22.04
echo "Hello from the container!" > /my-data/hello.txt
# You should also be able to see the hello.txt file on your host system
cat my-data/hello.txt
exit
----------------------------------------------------------------------------------------------------
Use cases for database
----------------------------------------------------------------------------------------------------
A few key considerations when running databases in containers:
Use volume(s) to persist data: The entire reason for section above was to give you an understanding of how to avoid data loss. Generally databases will store its data at one or more known paths. You should identify those and mount volumes to those locations in the containers to ensure data persists beyond the container.
Use bind mount(s) for additional config: Often databases use configuration files to influence runtime behavior. You can create these files on your host system, and then use a bind mount to place them in the correct location within the container to be read upon startup.
Set environment variables: In addition to configuration files many databases use environment variables to influence runtime behavior (for example setting the admin password). Identify these variables and set the accordingly.
Postgres
docker run -d --rm \
-v pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=foobarbaz \
-p 5432:5432 \
postgres:15.1-alpine
# With custom postresql.conf file
docker run -d --rm \
-v pgdata:/var/lib/postgresql/data \
-v ${PWD}/postgres.conf:/etc/postgresql/postgresql.conf \
-e POSTGRES_PASSWORD=foobarbaz \
-p 5432:5432 \
postgres:15.1-alpine -c 'config_file=/etc/postgresql/postgresql.conf'
Mongo
docker run -d --rm \
-v mongodata:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=foobarbaz \
-p 27017:27017 \
mongo:6.0.4
# With custom mongod.conf file
docker run -d --rm \
-v mongodata:/data/db \
-v ${PWD}/mongod.conf:/etc/mongod.conf \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=foobarbaz \
-p 27017:27017 \
mongo:6.0.4 --config /etc/mongod.conf
Redis
docker run -d --rm \
-v redisdata:/data \
redis:7.0.8-alpine
# With custom redis.conf file
docker run -d --rm \
-v redisdata:/data \
-v ${PWD}/redis.conf:/usr/local/etc/redis/redis.conf \
redis:7.0.8-alpine redis-server /usr/local/etc/redis/redis.conf
MySQL
docker run -d --rm \
-v mysqldata:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=foobarbaz \
mysql:8.0.32
# With custom conf.d
docker run -d --rm \
-v mysqldata:/var/lib/mysql \
-v ${PWD}/conf.d:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=foobarbaz \
mysql:8.0.32
Elasticsearch
docker run -d --rm \
-v elasticsearchdata:/usr/share/elasticsearch/data
-e ELASTIC_PASSWORD=foobarbaz \
-e "discovery.type=single-node" \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:8.6.0
Programme runtimes:
# https://hub.docker.com/_/python
docker run -it --rm python:3.11.1
# https://hub.docker.com/_/node
docker run -it --rm node:18.13.0
# https://hub.docker.com/_/php
docker run -it --rm php:8.1
# https://hub.docker.com/_/ruby
docker run -it --rm ruby:alpine3.17
-----------------------------------------------------CLI------------------------------------
docker run -i stedolan/jq <sample-data/test.json '.key_1 + .key_2'
docker run -i --rm busybox:1.36.0 sed 's/file./file!/g' <sample-data/test.txt
AWS: # Bind mount the credentials into the container
docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli:2.9.18 s3 ls
GCP:
# Bind mount the credentials into the container
docker run --rm -v ~/.config/gcloud:/root/.config/gcloud gcr.io/google.com/cloudsdktool/google-cloud-cli:415.0.0 gsutil ls
# Why is the container image so big 😭?! 2.8GB
0 Comments