Introduction to Containers
or: How I Learned to Stop Worrying and Love the Whale
CC-BY 4.0
Image Source: KOTA LIHAT by Bernard Spragg
$ whoami
Bob Killen
Research \
Cloud Administrator
rkillen@umich.edu
@mrbobbytables
Jeff Sica
Research \
Database Administrator
jsica@umich.edu
@jeefy
Before we Begin
Install Docker / Docker Compose
<distro> = centos, debian, fedora, ubuntu
What is a Container? (the 30,000ft version)
A means to easily isolate, package, deliver, and deploy code.
Image Source: HANJIN container by John A.
A “Shipping Container”�for your code.
What a Container is Not
* Some “Sandbox” containerizers spin up a container within a VM for each container.
Why Are Containers Becoming a Thing?
Why Are Containers Becoming a Thing?
Why are containers important for [role]?
Containerization Concepts
Old Method
New Method
Containerization Concepts
Old Methodologies
New Methodologies
"I like putting apps into containers because then I can pretend they're not my problem."
@sadoperator
Image Source: Hyundai
What is a Container...Really?
What is a Container...Really?
A process
What is a Container...Really?
A process
(with some additional properties)
What is a Container...Really?
What is a Container (The Technical Version)?
Linux Namespaces |
Process ID Number (PID) |
Network (NET) |
Interprocess Communication (IPC) |
Unix Time-sharing System (UTS) |
User |
Mount (MNT) |
A Brief History
1982 | |
2000 | |
2005 | |
2008 | |
2013 | |
2014 | |
2015 |
Container “Components”
Container Runtime | Image | Container |
Governing process that downloads and executes a container image. | Immutable bundle containing an application and its runtime dependencies. | Running instance of the image. |
Image Source: docker.com
Container vs VM
Image Source: docker.com
What is Docker?
Image Source: docker.com
Container Lifecycle
(The Basics)
Image Source: bernswaelz
Running a Container
$ docker run alpine echo hello from alpine!
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Image is not found locally.
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Pulls image from remote source.
Image is not found locally.
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Pulls image from remote source.
Image is verified.
Image is not found locally.
Running a Container
$ docker run alpine echo hello from alpine!
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
cd784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
hello from alpine!
$
Image is verified.
Instance of image is run executing command:
echo hello from alpine!
Pulls image from remote source.
Image is not found locally.
What Happened?
$ docker images
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 3f53bb00af94 13 days ago 4.41MB
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 3f53bb00af94 13 days ago 4.41MB
Image was pulled and stored locally.
(we’ll explore this more later)
What Happened?
$ docker ps -a
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
ebf7c76e62f9 alpine "echo hello from alp…" 2 minutes ago
STATUS PORTS NAMES
Exited (0) 2 minutes ago confident_stallman
continued
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
ebf7c76e62f9 alpine "echo hello from alp…" 2 minutes ago
STATUS PORTS NAMES
Exited (0) 2 minutes ago confident_stallman
Container given unique ID
continued
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
ebf7c76e62f9 alpine "echo hello from alp…" 2 minutes ago
STATUS PORTS NAMES
Exited (0) 2 minutes ago confident_stallman
Container given unique ID
Time since it was started
continued
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
ebf7c76e62f9 alpine "echo hello from alp…" 2 minutes ago
STATUS PORTS NAMES
Exited (0) 2 minutes ago confident_stallman
Container given unique ID
Time since it was started
Container status
continued
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
ebf7c76e62f9 alpine "echo hello from alp…" 2 minutes ago
STATUS PORTS NAMES
Exited (0) 2 minutes ago confident_stallman
Container given unique ID
Time since it was started
Container status
Unique random name
continued
What Happened?
$ docker ps -a -q
ebf7c76e62f9
$
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
Shell inside container
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
Shell inside container
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
02816f632397
/ #
Shell inside container
Container ID is used as hostname
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
02816f632397
/ # whoami
Shell inside container
Container ID is used as hostname
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
02816f632397
/ # whoami
root
/ #
Shell inside container
Container ID is used as hostname
Different User inside container
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
02816f632397
/ # whoami
root
/ # cat /etc/os-release
Shell inside container
Container ID is used as hostname
Different User inside container
Running an Interactive Container
$ docker run -i -t alpine /bin/sh
/ #
/ # hostname
02816f632397
/ # whoami
root
/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.8.2
PRETTY_NAME="Alpine Linux v3.8"
HOME_URL="http://alpinelinux.org"
BUG_REPORT_URL="http://bugs.alpinelinux.org"
Shell inside container
Container ID is used as hostname
Different User inside container
Independant OS from Host
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 3f53bb00af94 13 days ago 4.41MB
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 3f53bb00af94 13 days ago 4.41MB
No new images pulled.
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED 02816f632397 alpine "/bin/sh" 27 minutes ago
ebf7c76e62f9 alpine "echo hello from alp…" 2 days ago
STATUS PORTS NAMES
Exited (0) 1 second ago ecstatic_mendeleev
Exited (0) 2 days ago confident_stallman
continued
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED 02816f632397 alpine "/bin/sh" 27 minutes ago
ebf7c76e62f9 alpine "echo hello from alp…" 2 days ago
STATUS PORTS NAMES
Exited (0) 1 second ago ecstatic_mendeleev
Exited (0) 2 days ago confident_stallman
continued
Container given unique ID
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED 02816f632397 alpine "/bin/sh" 27 minutes ago
ebf7c76e62f9 alpine "echo hello from alp…" 2 days ago
STATUS PORTS NAMES
Exited (0) 1 second ago ecstatic_mendeleev
Exited (0) 2 days ago confident_stallman
continued
Container given unique ID
Unique random name
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Daemonized Container is Running
In browser visit:
http://localhost
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Image is not found locally.
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Pulls needed image layers.
Image is not found locally.
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Pulls needed image layers.
Image is verified.
Image is not found locally.
Daemonizing a Container
$ docker run -d -p 80:80 nginx:stable-alpine
Unable to find image 'nginx:stable-alpine' locally
stable-alpine: Pulling from library/nginx
cd784148e348: Already exists
12b08f7ef616: Pull complete
65071a4e699c: Pull complete
9936647427be: Pull complete
Digest: sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96
Status: Downloaded newer image for nginx:stable-alpine
75a606c744eb2ac6c73067b8c2a861fef66cd4d03dbf29f7db8b7a6700568211
$
Pulls needed image layers.
Image is verified.
Image is not found locally.
Instance of image is started in background with Container ID: 75a606c744eb
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx stable-alpine c5b6f731fbc0 2 weeks ago 17.7MB
alpine latest 3f53bb00af94 2 weeks ago 4.41MB
What Happened?
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx stable-alpine c5b6f731fbc0 2 weeks ago 17.7MB
alpine latest 3f53bb00af94 2 weeks ago 4.41MB
New image nginx:stable-alpine was pulled and cached
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Container given unique ID
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Container given unique ID
Default command executed
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Container given unique ID
Default command executed
Container status
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Container given unique ID
Port Mapping
Default command executed
Container status
What Happened?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Container given unique ID
Port Mapping
Default command executed
Container status
Unique random name
What Happened?
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
02816f632397 alpine "/bin/sh" 5 hours ago
ebf7c76e62f9 alpine "echo hello from alp…" 3 days ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
Exited (0) 4 hours ago ecstatic_mendeleev
Exited (0) 3 days ago confident_stallman
continued
Stopping a Container
$ docker stop <container name | container ID>
Stopping a Container
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up About an hour 0.0.0.0:80->80/tcp loving_lederberg
continued
Stopping a Container
$ docker stop loving_lederberg
Stopping a Container
$ docker stop loving_lederberg
loving_lederberg
$
Stopping a Container
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Exited (0) 1 minutes ago 0.0.0.0:80->80/tcp loving_lederberg
continued
Starting a Container
$ docker start <container name | container ID>
Starting a Container
$ docker start loving_lederberg
loving_lederberg
$
Starting a Container
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
75a606c744eb nginx:stable-alpine "nginx -g 'daemon of…" About an hour ago
STATUS PORTS NAMES
Up 24 seconds 0.0.0.0:80->80/tcp loving_lederberg
continued
Viewing Container Logs
$ docker logs <container name | container ID>
Container Logs
$ docker logs loving_lederberg
Container Logs
$ docker logs loving_lederberg
172.17.0.1 - - [09/Jan/2019:14:27:05 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"
172.17.0.1 - - [09/Jan/2019:14:27:05 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"
$
Cleaning Up
Image Source: Nuke HD by dudex
Deleting containers
$ docker rm <container name | container ID>
Deleting containers
$ docker rm $(docker ps -a -q)
Summary - Container Lifecycle
Command Reference
Container Lifecycle | |
docker run <image> <optional command> | Spawns and runs an instance of the Docker image |
docker run -i -t <image> <optional command> | Spawns an interactive instance of the Docker image |
docker run -d <image> <optional command> | Spawns a daemonized instance of the Docker image |
docker start <container name | container ID> | Starts a stopped container |
docker stop <container name | container ID> | Stops a running container |
docker rm <container name | container ID> | Deletes a stopped container |
docker container prune | Deletes all stopped containers |
Command Reference
Container Status | |
docker ps | Displays status for all running containers. |
docker ps -a | Displays status of all containers. |
docker ps -a -q | Displays only the container IDs |
Container Images | |
docker images | Displays locally cached container images. |
Container logs | |
docker logs <container name | container ID> | Displays locally cached container images. |
Images
What is a Container Image?
What is a Container Image?
What is a Container Image?
Layer Hierarchy
myhadoop:latest
myspark:latest
mynode:latest
7bff100f35cb
42acf078bf60
0246bb21855f
59b059d445c1
f1969daa376c
8d54164793e0
0246bb21855f
59b059d445c1
c6d52c0daf49
8bc7877153ca
d4fb3d7df954
59b059d445c1
Layer Hierarchy
myhadoop:latest
myspark:latest
mynode:latest
7bff100f35cb
42acf078bf60
0246bb21855f
59b059d445c1
f1969daa376c
8d54164793e0
0246bb21855f
59b059d445c1
c6d52c0daf49
8bc7877153ca
d4fb3d7df954
59b059d445c1
Layer Hierarchy
myhadoop:latest
myspark:latest
mynode:latest
7bff100f35cb
42acf078bf60
0246bb21855f
59b059d445c1
f1969daa376c
8d54164793e0
0246bb21855f
59b059d445c1
c6d52c0daf49
8bc7877153ca
d4fb3d7df954
59b059d445c1
myhadoop:latest
myspark:latest
mynode:latest
Layer Hierarchy
What Happens When a Container is Run
What Happens When a Container is Run
How do you build those layers...
Dockerfile
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get -y install nginx
COPY website /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Dockerfile Instruction: FROM
FROM <image name>
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get -y install nginx
COPY website /var/www
...
Dockerfile Instruction: RUN
RUN <command>
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get -y install nginx
COPY website /var/www
...
Dockerfile Instruction: RUN
RUN <command>
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get -y install nginx
COPY website /var/www
...
Dockerfile Instruction: COPY
COPY <source host path> <dest container path>
...
COPY website /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Dockerfile Instruction: EXPOSE
EXPOSE <ports>
...
COPY website /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Dockerfile Instruction: CMD
CMD <command>
...
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Dockerfile Instruction: ENTRYPOINT
ENTRYPOINT <command>
...
EXPOSE 80 443
ENTRYPOINT [“nginx”]
CMD ["-g", "daemon off;"]
Dockerfile Instruction: ENV
ENV <key>=<value>
...
ENV ENVIRONMENT=prod
EXPOSE 80 443
...
Dockerfile Instruction: ENV
ENV <key>=<value>
...
ENV ENVIRONMENT=prod \
NGINX_VERSION=1.14.0
EXPOSE 80 443
...
Other Useful Dockerfile Instructions
ADD | Similar to COPY that can fetch remote resources. |
ARG | Pass arguments to used during the image build. |
LABEL | Add additional metadata to the image. |
ONBUILD | Instruction that will be executed when image is used as a base for another image. |
SHELL | Override default shell. |
USER | Change User and Group that the container executes as. |
VOLUME | Flags a directory within the image that should be persisted when a container is started. |
WORKDIR | Define the working directory. |
Building an Image
$ docker build -t <repository>:<tag> <path>
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
Step 4/6 : COPY website /var/www
---> 1830a2706de4
Step 5/6 : EXPOSE 80 443
---> Running in 31e60cf54092
Removing intermediate container 31e60cf54092
---> 4adc00a6e923
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in f445e6f565ff
Removing intermediate container f445e6f565ff
---> a0cbc29fc92e
Successfully built a0cbc29fc92e
Successfully tagged mynginx:latest
continued
continued
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
continued
Directory is compressed (tar) and send to Docker Daemon.
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
continued
Directory is compressed (tar) and send to Docker Daemon.
Downloads base image.
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
continued
Directory is compressed (tar) and send to Docker Daemon.
Instruction (RUN) is executed in intermediate container.
Downloads base image.
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
continued
Directory is compressed (tar) and send to Docker Daemon.
Instruction (RUN) is executed in intermediate container.
Intermediate container is removed if instruction completed successfully.
Downloads base image.
Build Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0a8536502efb
Get:1 http://security.ubuntu.com/ubuntu bionic-security
...
Reading package lists...
Removing intermediate container 0a8536502efb
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Running in f877470644a8
Reading package lists...
...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container f877470644a8
---> b6d51460362e
continued
Directory is compressed (tar) and send to Docker Daemon.
Instruction (RUN) is executed in intermediate container.
Intermediate container is removed if instruction completed successfully.
Downloads base image.
Results “committed” to image.
Build Example
Step 4/6 : COPY website /var/www
---> 1830a2706de4
Step 5/6 : EXPOSE 80 443
---> Running in 31e60cf54092
Removing intermediate container 31e60cf54092
---> 4adc00a6e923
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in f445e6f565ff
Removing intermediate container f445e6f565ff
---> a0cbc29fc92e
Successfully built a0cbc29fc92e
Successfully tagged mynginx:latest
continued
Image build completed successfully.
Build Example
Step 4/6 : COPY website /var/www
---> 1830a2706de4
Step 5/6 : EXPOSE 80 443
---> Running in 31e60cf54092
Removing intermediate container 31e60cf54092
---> 4adc00a6e923
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in f445e6f565ff
Removing intermediate container f445e6f565ff
---> a0cbc29fc92e
Successfully built a0cbc29fc92e
Successfully tagged mynginx:latest
$
continued
Image build completed successfully.
Image tagged.
Build Cache Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Using cache
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Using cache
---> b6d51460362e
Step 4/6 : COPY website /var/www
---> Using cache
---> 1830a2706de4
Step 5/6 : EXPOSE 80 443
---> Using cache
---> 4adc00a6e923
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> a0cbc29fc92e
Successfully built a0cbc29fc92e
Successfully tagged mynginx:latest
continued
continued
Build Cache Example
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Using cache
---> d23ca2e87023
Step 3/6 : RUN apt-get -y install nginx
---> Using cache
---> b6d51460362e
Step 4/6 : COPY website /var/www
---> Using cache
---> 1830a2706de4
Step 5/6 : EXPOSE 80 443
---> Using cache
---> 4adc00a6e923
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> a0cbc29fc92e
Successfully built a0cbc29fc92e
Successfully tagged mynginx:latest
continued
continued
Image cache used for subsequent builds.
Failed Builds
$ docker rmi mynginx
Untagged: mynginx:latest
Deleted: sha256:...
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0e1bfd467e44
Removing intermediate container 0e1bfd467e44
---> 10a25e9b38e3
Step 3/6 : RUN apt-get -y install nginx
---> Running in d3ad013c6afd
Removing intermediate container d3ad013c6afd
---> 939dccaf4632
Step 4/6 : COPY website /var/www
COPY failed: stat /var/lib/docker/tmp/docker-builder918141210/website: no such file or directory
$
Renamed website directory.
Failed Builds
$ docker rmi mynginx
Untagged: mynginx:latest
Deleted: sha256:...
$ docker build -t mynginx .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM ubuntu:18.04
---> 1d9c17228a9e
Step 2/6 : RUN apt-get update
---> Running in 0e1bfd467e44
Removing intermediate container 0e1bfd467e44
---> 10a25e9b38e3
Step 3/6 : RUN apt-get -y install nginx
---> Running in d3ad013c6afd
Removing intermediate container d3ad013c6afd
---> 939dccaf4632
Step 4/6 : COPY website /var/www
COPY failed: stat /var/lib/docker/tmp/docker-builder918141210/website: no such file or directory
$
Renamed website directory.
Successful changes still committed to image.
Failed Builds
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 939dccaf4632 13 minutes ago 171MB
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
nginx stable-alpine c5b6f731fbc0 3 weeks ago 17.7MB
alpine latest 3f53bb00af94 3 weeks ago 4.41MB
Intermediate image of successful build steps.
Image Names and Tags
Image Names and Tags
<registry>/<namespace>/<image name>:<tag>
<registry> |
|
<namespace> |
|
<image name> |
|
<tag> |
|
Image Names and Tags Examples
Tagging an Image
$ docker tag <image name | image ID>
Tagging an Image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
$
$ docker tag ubuntu:18.04 ubuntu:bionic
$
$ docker images
Tagged image
Tagging an Image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
$
$ docker tag ubuntu:18.04 ubuntu:bionic
$
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
ubuntu bionic 1d9c17228a9e 2 weeks ago 86.7MB
Tagged image
Same image ID
Removing an Image
$ docker rmi <image name>:<tag>
Removing an Image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
ubuntu bionic 1d9c17228a9e 2 weeks ago 86.7MB
$ docker rmi ubuntu:bionic
Removing an Image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
ubuntu bionic 1d9c17228a9e 2 weeks ago 86.7MB
$ docker rmi ubuntu:bionic
Untagged: ubuntu:bionic
$
Image untagged
Removing an Image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 1d9c17228a9e 2 weeks ago 86.7MB
ubuntu bionic 1d9c17228a9e 2 weeks ago 86.7MB
$ docker rmi ubuntu:bionic
Untagged: ubuntu:bionic
$ docker rmi ubuntu:18.04
Untagged: ubuntu@sha256:868fd30a0e47b8d8ac485df174795b5e2fe8a6c8f056cc707b232d65b8a1ab68
Deleted: sha256:1d9c17228a9e80a0a23927f24f3cf17d012cf0bb3eae5e3541a8c6987ab9bd5a
Deleted: sha256:3288cd6e6e7d42bcb4a74121b412c42a11f96da52685e42dbf9de6a747a55c6b
Deleted: sha256:b1636589630239bdb9153f95ac564bcd2afd9202aaf8511cbf5a9a37e03daf35
Deleted: sha256:043f492f40c539cfe7cee4cb8aae00ed1d5b19e864fbe6ea35ec92a2333bacc4
Deleted: sha256:2fb7bfc6145d0ad40334f1802707c2e2390bdcfc16ca636d9ed8a56c1101f5b9
$
Image untagged
Image deleted
Docker Hub + Docker Login
$ docker login <registry address>
$ docker login
Username: mrbobbytables
Password:
Login Succeeded
$
Pulling an Image
$ docker pull <image name>:<image tag>
Pulling an Image
$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
84ed7d2f608f: Pull complete
be2bf1c4a48d: Pull complete
a5bdc6303093: Pull complete
e9055237d68d: Pull complete
Digest: sha256:868fd30a0e47b8d8ac485df174795b5e2fe8a6c8f056cc707b232d65b8a1ab68
Status: Downloaded newer image for ubuntu:18.04
Pushing an Image
$ docker push <image name>:<image tag>
Pushing an Image
$ docker tag mynginx mrbobbytables/mynginx
$ docker push mrbobbytables/mynginx
The push refers to repository [docker.io/mrbobbytables/mynginx]
e40e8eb7296d: Pushed
7efdc7f1001c: Pushed
8e26e7457281: Pushed
2c77720cf318: Mounted from ubuntu:18.04
1f6b6c7dc482: Mounted from ubuntu:18.04
c8dbbe73b68c: Mounted from ubuntu:18.04
2fb7bfc6145d: Mounted from ubuntu:18.04
latest: digest: sha256:c99b42b130c9e8cf17ce15f1c136047c3b99391a8caa40d60d78c022b0cb57ee size: 1781
Pushing an Image
$ docker tag mynginx mrbobbytables/mynginx
$ docker push mrbobbytables/mynginx
The push refers to repository [docker.io/mrbobbytables/mynginx]
e40e8eb7296d: Pushed
7efdc7f1001c: Pushed
8e26e7457281: Pushed
2c77720cf318: Mounted from ubuntu:18.04
1f6b6c7dc482: Mounted from ubuntu:18.04
c8dbbe73b68c: Mounted from ubuntu:18.04
2fb7bfc6145d: Mounted from ubuntu:18.04
latest: digest: sha256:c99b42b130c9e8cf17ce15f1c136047c3b99391a8caa40d60d78c022b0cb57ee size: 1781
Layers already present in Registry
Pushing an Image
$ docker tag mynginx mrbobbytables/mynginx
$ docker push mrbobbytables/mynginx
The push refers to repository [docker.io/mrbobbytables/mynginx]
e40e8eb7296d: Pushed
7efdc7f1001c: Pushed
8e26e7457281: Pushed
2c77720cf318: Mounted from ubuntu:18.04
1f6b6c7dc482: Mounted from ubuntu:18.04
c8dbbe73b68c: Mounted from ubuntu:18.04
2fb7bfc6145d: Mounted from ubuntu:18.04
latest: digest: sha256:c99b42b130c9e8cf17ce15f1c136047c3b99391a8caa40d60d78c022b0cb57ee size: 1781
Layers already present in Registry
Layers pushed
Summary - Images
Command Reference
Container Images | |
docker images | Displays locally cached container images. |
docker build -t <image name> <dockerfile path> | Builds an image. |
docker rmi <image tag> | Untags and/or removes an image. |
docker pull <image name> | Pulls an image from a registry. |
docker push <image name> | Pushes an image to a registry. |
Docker Hub (Image Registries) | |
docker login | Authenticates to a remote registry. |
Dockerfile Instruction Reference
FROM | Specifies which image should be used as its base image. |
RUN | Executes command(s) within the container. |
COPY | Copies files and directories from a relative location on the host to the destination within the container image. |
EXPOSE | Informs Docker that the specified ports should be exposed outside the container. |
CMD | Provides default command to be run by the container. |
ENTRYPOINT | Provides default executable for the container. |
ENV | Sets environment variables within the container. |
Dockerfile Instruction Reference
ADD | Similar to COPY that can fetch remote resources. |
ARG | Pass arguments to used during the image build. |
LABEL | Add additional metadata to the image. |
ONBUILD | Instruction that will be executed when image is used as a base for another image. |
SHELL | Override default shell. |
USER | Change User and Group that the container executes as. |
VOLUME | Flags a directory within the image that should be persisted when a container is started. |
WORKDIR | Define the working directory. |
Exercise:
Getting to Know Images
Image Source: Captain Albert E. Theberge, NOAA Corps
Networking
Image Source: pxhere
Container Networking Overview
Why Private Networks?
Why Private Networks?
Application stacks can be Isolated from each other and still be made externally available.
Multi-Host Network
Private Container Networks can span hosts when a “Swarm” cluster is created.
Container Network Model
Container Network Drivers
(Note: Tutorial will only use bridge network)
bridge | A basic virtual switch bound to a single host (default) |
host | Shares network namespace with host (no private network) |
null | No network at all. |
macvlan | A mock “physical” device with a MAC address attached to a specific adapter. |
overlay | “Overlays” or encapsulates a virtual network on top of a regular network (vxlan) |
Listing Networks
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
6a840fc500f8 bridge bridge local
e9a8161ec260 host host local
e97466e77f45 none null local
Default Networks
Creating a Network
$ docker network create <network name>
Creating a Network
$ docker network create mynetwork
2a1566734b671d2ddc550c77c08edea4c1efc56391ebbcf22526fbb0d6c80c19
$
Network ID
Creating a Network
$ docker network create mynetwork
2a1566734b671d2ddc550c77c08edea4c1efc56391ebbcf22526fbb0d6c80c19
$
$
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
6a840fc500f8 bridge bridge local
e9a8161ec260 host host local
2a1566734b67 mynetwork bridge local
e97466e77f45 none null local
$
Network ID
Created Network
Using a Created Network
$ docker run -d --network <network name> ...
Revisiting EXPOSE and Published Ports
EXPOSE <ports>
EXPOSE 80 443
STATUS PORTS
Up 3 seconds 80/tcp
Revisiting EXPOSE and Published Ports
EXPOSE 80 443
TUS PORTS
conds 0.0.0.0:80->80/tcp
$ docker run -d -p [ip]:<host port>:<container port>
docker run -d -p 80:80 ...
More on Published Ports
Container Identity
$ docker run -d --name <container name> --network ..
Using Networks and Named Containers
$ docker run -d --network mynetwork --name mynginx nginx:stable-alpine
fb256726d1b826fd87b8181f0faeef4b4757223466359f8ccc79f1a00e134ed2
$ docker run -it --network mynetwork nicolaka/netshoot /bin/bash
bash-4.4# curl mynginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</body>
</html>
$
Using Container ID the service (nginx running on port 80) can be accsed from another container on the same network.
Summary - Networking
Command Reference
Container Networks | |
docker network ls | Lists Container networks. |
docker network create <network name> | Creates a Container network. |
docker network rm <network name> | Deletes a container network |
Using Container Networks | |
docker run -d --network <network name> | Starts container on supplied network. |
docker run -d --name <container name> | Assigns the container a friendly name and dns name. |
Exercise:
Exploring Container Networking
Storage
Storage Overview
Storage Overview
Using a Mount
$ docker run -d -v <host path>:<container path>:[ro|rw]
Bind Mount Example
$ echo -e “Hello there.\n General Kenobi!” > /tmp/www/index.html
$
$ docker run -d -v /tmp/www:/usr/share/nginx/html -p 80:80 nginx:stable-alpine
24103e7dac126cf2e4087252d3895f9598c01fba93668d64a983395d00740873
$
Mounts: /tmp/www -> /usr/share/nginx/html
Bind Mount Example
$ echo -e “Hello there.\n General Kenobi!” > /tmp/www/index.html
$
$ docker run -d -v /tmp/www:/usr/share/nginx/html -p 80:80 nginx:stable-alpine
24103e7dac126cf2e4087252d3895f9598c01fba93668d64a983395d00740873
$
$ curl localhost
Hello There.
General Kenobi!
$
Mounts: /tmp/www -> /usr/share/nginx/html
Content stored on host served up from the container.
Bind Mount Example
$ docker stop 24103e && docker rm 24103e
24103e
24103e
$
Stop and delete previous container.
Bind Mount Example
$ docker stop 24103e && docker rm 24103e
24103e
24103e
$ docker run -d -v /tmp/www:/usr/share/nginx/html -p 80:80 nginx:stable-alpine
723d26858cd75a01d130f5720cf9cfdaacd9d0a8470df597db64cebe9e1b64dd
$
New Container with same mount:� /tmp/www -> /usr/share/nginx/html
Stop and delete previous container.
Bind Mount Example
$ docker stop 24103e && docker rm 24103e
24103e
24103e
$ docker run -d -v /tmp/www:/usr/share/nginx/html -p 80:80 nginx:stable-alpine
723d26858cd75a01d130f5720cf9cfdaacd9d0a8470df597db64cebe9e1b64dd
$
$ curl localhost
Hello There.
General Kenobi!
$
$ docker stop 24103e && docker rm 24103e
24103e
24103e
$ docker run -d -v /tmp/www:/usr/share/nginx/html -p 80:80 nginx:stable-alpine
723d26858cd75a01d130f5720cf9cfdaacd9d0a8470df597db64cebe9e1b64dd
$
$ curl localhost
Hello There.
General Kenobi!
$
Content persisted across container deletions.
New Container with same mount:� /tmp/www -> /usr/share/nginx/html
Content not removed when container was removed
Stop and delete previous container.
Volumes
Working with the volume command
$ docker volume <create|ls|inspect|rm>
Working with Volumes: create
$ docker volume create myvol
myvol
$
Creates volume with default driver
Working with Volumes: ls
$ docker volume ls
DRIVER VOLUME NAME
local myvol
$
Lists all volumes
Working with Volumes: inspect
$ docker volume inspect myvol
[
{
"CreatedAt": "2019-01-25T15:34:22Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": {},
"Scope": "local"
}
]
Information regarding the volume
Working with Volumes: inspect
$ docker volume inspect myvol
[
{
"CreatedAt": "2019-01-25T15:34:22Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": {},
"Scope": "local"
}
]
Information regarding the volume
Created volumes using local driver are stored in /var/lib/docker/volumes
Working with Volumes: rm
$ docker volume rm myvol
myvol
$
$ docker volume ls
DRIVER VOLUME NAME
Deletes the volume
Using Volumes
$ docker run -d -v <volume name>:<container path> ...
$ docker run -d -v myvol:/var/lib/mysql mysql ...
Using Volumes
$ docker volume ls
DRIVER VOLUME NAME
local myvol
$ docker run -d -v myvol:/var/lib/mysql mysql
4d732d66630f18c00186d1a29159f0dcb750ef6de300406fc5e269089404e36e
$
Local volume attached to container
Using Volumes
$ docker volume ls
DRIVER VOLUME NAME
local myvol
$ docker run -d -v myvol:/var/lib/mysql mysql
4d732d66630f18c00186d1a29159f0dcb750ef6de300406fc5e269089404e36e
$ docker stop 4d732 && docker rm 4d732
4d732
4d732
$ docker volume ls
DRIVER VOLUME NAME
local myvol
Local volume attached to container.
Volume persists after container deleted.
Revisiting VOLUME Directive
VOLUME <path>
VOLUME /var/lib/mysql
$ docker run -d mysql
76bf01fc976643b5f224dde5bc3a6a150827d6e4d3024a05e5c38dfa0e20e594
$ docker volume ls
DRIVER VOLUME NAME
local abff9cbcc0f9df64f0efe004c90a5404a1ffb2c001fde1386ee8ba5e0776035f
Revisiting VOLUME Directive
$ docker rm 76bf0
76bf0
$ docker volume ls
DRIVER VOLUME NAME
local abff9cbcc0f9df64f0efe004c90a5404a1ffb2c001fde1386ee8ba5e0776035f
$
Removing the container does NOT
delete the auto-created volume.
Summary
Command Reference
Container Volumes | |
docker volume ls | Lists volumes. |
docker volume create <volume name> | Creates a volume. |
docker volume inspect <volume name> | Inspects a volume. |
docker volume rm <volume name> | Removes a volume. |
Using Volumes | |
docker run -d -v <host path>:<container path> | Mounts a host directory into a container. |
docker run -d -v <volume name>:<container path> | Mounts a volume into a container. |
Exercise:
Storage
Inspecting and Debugging
Inspecting and Debugging
Inspect
docker <*|image|network|volume> inspect <id>
Inspect
docker <*|image|network|volume> inspect <id>
Inspect: image
$ docker image inspect nginx:stable-alpine
[
{
"Id": "sha256:c5b6f731fbc07a20c352256b94891c178e687910dd3fd5318c7bb0b6f6962780",
"RepoTags": [
"nginx:stable-alpine"
],
"RepoDigests": [
"nginx@sha256:e3f77f7f4a6bb5e7820e013fa60b96602b34f5704e796cfd94b561ae73adcf96"
],
"Parent": "",
"Comment": "",
"Created": "2018-12-21T01:22:30.534924761Z",
...
Inspect: network
$ docker network inspect mynetwork
[
{
"Name": "mynetwork",
"Id": "07cc816ffe6e272364004c71355299ee283038cd0bca65bcda58eab0b87859d1",
"Created": "2019-01-20T22:04:57.4853317Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
...
Inspect: volume
$ docker volume inspect myvol
[
{
"CreatedAt": "2019-01-27T15:09:31Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": null,
"Scope": "local"
}
]
Inspect: container
$ docker inspect frosty_benz
[
{
"Id": "f0ab9306a8cbdc51d890213d895af20362df452a186bc9ac1e7518f73bccf040",
"Created": "2019-01-27T19:19:44.9049437Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
...
Inspect: container
$ docker inspect frosty_benz
[
{
"Id": "f0ab9306a8cbdc51d890213d895af20362df452a186bc9ac1e7518f73bccf040",
"Created": "2019-01-27T19:19:44.9049437Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
...
LOTS of information!
Formatted Output
Formatted Output Examples
$ docker inspect frosty_benz --format=”{{ .Config.Image }}”
nginx:stable-alpine
$
$ docker inspect frosty_benz --format="{{ .NetworkSettings.IPAddress }}"
172.17.0.2
$
$ docker image inspect nginx:stable-alpine --format="{{ .Created }}"
2018-12-21T01:22:30.534924761Z
$
$ docker network inspect mynetwork --format="{{ (index .IPAM.Config 0).Subnet }}"
172.20.0.0/16
Attaching to a Running Container
docker attach <container name>
Attaching to a Container
$ docker run -i -t alpine /bin/sh
/ # hostname
f6022e824572
/ # exit
$
$ docker start f6022e824572
f6022e824572
$
$ docker attach f6022e824572
/ # hostname
f6022e824572
/ #
Exec’ing into a Running Container
docker exec <container name> <command>
Executing a Command in a Container
$ docker run -d nginx:alpine-stable
599d394ad9ec1952c68ac33347678e6de9b9dce9ab5c05c5c5aedb3ced91fc20
$
$ docker exec 599d394ad9ec hostname
599d394ad9ec
$
$ docker exec 599d394ad9ec cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.8.2
...
Exec’ing into a Container
$ docker run -d nginx:alpine-stable
599d394ad9ec1952c68ac33347678e6de9b9dce9ab5c05c5c5aedb3ced91fc20
$
$ docker exec -i -t 599d394ad9ec /bin/sh
/ #
/ # hostname
599d394ad9ec
/ #
Attach vs Exec
/ # ps aux
PID USER TIME COMMAND
1 root 0:00 /bin/sh
15 root 0:00 ps aux
/ # ps aux
PID USER TIME COMMAND
1 root 0:00 /bin/sh
6 root 0:00 /bin/sh
13 root 0:00 ps aux
Attach
Exec
Summary
Command Reference
Inspect | |
docker inspect | View low-level information on a container. |
docker image inspect | View low-level information on an image. |
docker network inspect | View low-level information on a network. |
docker volume inspect | View low-level information on a volume. |
Attach and Exec | |
docker attach <container name> | Attaches to console of container. |
docker exec <container name> <command> | Executes a command within a container. |
Exercise:
Inspecting and Troubleshooting
Developer Workflow
Developer Workflow
Assumption:
You already have the application working locally.
Developer Workflow
Three step process
Developer Workflow
What that means
Step 1: Dockerfile
Developer Workflow
# For this example we're going to use Python
# Alpine is a lightweight OS that makes for smaller containers
FROM python:3.4-alpine
# Copy our current working directory contents into the /code folder
COPY . /code
# Set the default directory to be /code
WORKDIR /code
# Install Python dependencies
RUN pip install -r requirements.txt
# Set the default command to be `python app.py`
CMD ["python", "app.py"]
Developer Workflow
$ docker build -t flask_app .
...
$ docker run -d -p 6379:6379 --name redis redis:alpine
...
$ docker run -i -t -p 8080:8080 flask_app
We’re not done.
Step 2: Runtime Configuration
Developer Workflow
import time, redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
...�@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
Developer Workflow
import time, redis, os
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host=os.getenv(‘REDIS_HOST’, ‘redis’), port=os.getenv(‘REDIS_PORT’, ‘6379’))
...�@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=os.getenv(‘FLASK_PORT’, ‘8080’), debug=True)
Developer Workflow
$ docker build -t flask_app .
...
$ docker run -d -p 6379:6379 --name redis redis:alpine
...
$ docker run -i -t \
-p 8080:8080 \
-e REDIS_HOST=redis \
-e REDIS_PORT=6379 \
-e FLASK_PORT=8080 \
flask_app
We’re still not done.
Step 3: Docker Compose
Docker Compose
version: '3'
services:
web:
build: .
ports:
- "8080:8080"
volumes:
- .:/code
env_file:
- ./.env
redis:
image: "redis:alpine"
Docker Compose
$ docker-compose up
Docker Compose
$ docker-compose up
Starting docker-compose-example_redis_1 ... done
Starting docker-compose-example_web_1 ... done
Attaching to docker-compose-example_redis_1, docker-compose-example_web_1
Docker Compose
$ docker-compose up
Starting docker-compose-example_redis_1 ... done
Starting docker-compose-example_web_1 ... done
Attaching to docker-compose-example_redis_1, docker-compose-example_web_1
redis_1 | 1:C 18 Feb 2019 17:45:31.326 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 18 Feb 2019 17:45:31.326 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 18 Feb 2019 17:45:31.326 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 18 Feb 2019 17:45:31.328 * Running mode=standalone, port=6379.
web_1 | * Tip: There are .env files present. Do "pip install python-dotenv" to use them.
web_1 | * Serving Flask app "app" (lazy loading)
web_1 | * Environment: production
Best Practices & Tips
Security: Don’t run your container as root
Security: Just enough to get the job done
Security: read only filesystem
Security
$ docker run -d -p 80:80 --read-only \
--tmpfs /run:rw,noexec,nosuid,size=1m \
--tmpfs /var/cache/nginx:rw,noexec,nosuid,size=5m \
nginx:stable-alpine
5e2d8cf6b08f1e2a1dbb4446b1710057acfb5d6658234efbea082e3643e468c1
Security: read only filesystem
$ docker run -d -p 80:80 --read-only \
--tmpfs /run:rw,noexec,nosuid,size=1m \
--tmpfs /var/cache/nginx:rw,noexec,nosuid,size=5m \
nginx:stable-alpine
5e2d8cf6b08f1e2a1dbb4446b1710057acfb5d6658234efbea082e3643e468c1
$
read only
restricted tmpfs
Security: read only filesystem
$ docker run -d -p 80:80 --read-only \
--tmpfs /run:rw,noexec,nosuid,size=1m \
--tmpfs /var/cache/nginx:rw,noexec,nosuid,size=5m \
nginx:stable-alpine
5e2d8cf6b08f1e2a1dbb4446b1710057acfb5d6658234efbea082e3643e468c1
$
$ docker exec -it 5e2d8 touch /amireadonly
touch: /amireadonly: Read-only file system
$
read only
restricted tmpfs
Prevented writing to filesystem
Security: read only filesystem
$ docker run -d -p 80:80 --read-only \
--tmpfs /run:rw,noexec,nosuid,size=1m \
--tmpfs /var/cache/nginx:rw,noexec,nosuid,size=5m \
nginx:stable-alpine
5e2d8cf6b08f1e2a1dbb4446b1710057acfb5d6658234efbea082e3643e468c1
$
$ docker exec -it 5e2d8 touch /amireadonly
touch: /amireadonly: Read-only file system
$
docker exec -it 5e2d8 touch /run/amireadonly
$
$ docker exec -it 5e2d8 ls /run
amireadonly nginx.pid
read only
restricted tmpfs
Prevented writing to filesystem
Can write to tmpfs
Security: Linux Capabilities
Security: Linux Capabilities
Security: Linux Capabilities
Security: Linux Capabilities
Security: Linux Capabilities
AUDIT_WRITE | Write records to kernel auditing log. |
CHOWN | Make arbitrary changes to file UIDs and GIDs |
DAC_OVERRIDE | Bypass file read, write, and execute permission checks. |
FOWNER | Bypass permission checks on operations that normally require the file system UID of the process to match the UID of the file. |
FSETID | Don’t clear set-user-ID and set-group-ID permission bits when a file is modified. |
KILL | Bypass permission checks for sending signals. |
MKNOD | Create special files using mknod. |
Security: Linux Capabilities
NET_BIND_SERVICE | Bind a socket to internet domain privileged ports (port numbers less than 1024). |
NET_RAW | Use RAW and PACKET sockets. |
SETGID | Make arbitrary manipulations of process GIDs and supplementary GID list. |
SETFCAP | Set file capabilities. |
SETPCAP | Modify process capabilities. |
SETUID | Make arbitrary manipulations of process UIDs. |
SYS_CHROOT | Use chroot, change root directory. |