Back to the main page

Docker, first steps on OL8.2

Intro

This work is on OL8.2. To install Docker, add Docker repo.
$ dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
Use these commands to list repos.
$ dnf list docker-ce
$ dnf list docker-ce --showduplicates
The latest version of Docker install fails (RedHat now has buildah), so install next available version and start/enable service.
$ dnf install docker-ce --nobest
$ systemctl start docker
$ systemctl enable  docker

$ docker version
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.39 (downgraded from 1.40)
 Go version:        go1.12.17
 Git commit:        afacb8b
 Built:             Wed Mar 11 01:27:04 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       4c52b90
  Built:            Wed Jan  9 19:06:30 2019
  OS/Arch:          linux/amd64
  Experimental:     false
Big picture
Dickerfile                                                                              <-- search ----  
in source code repo, ----- build --->  Host - Container --- push ---->  Docker registry -- pull/run --->  Host
like GitLab
Docker proxy : it may happen that Docker doesn't honer system's http_proxy/https_proxy environment, hence it can't pull images from the Internet, like Docker Hub.
The resolution is to setup Docker environment for proxy, example:
Vi the file  /usr/lib/systemd/system/docker.service 
Under section [Service] add the line :  Environment="https_proxy=http://proxy-fqdn:80" 
Reload systemd manager configuration with the command:  systemctl daemon-reload 
Restart Docker service:  systemctl restart docker 
Verify change with the command:  systemctl show --property=Environment docker 
Expect to see:  Environment=https_proxy=http://proxy-fqdn:80  

Simple start, with busybox (collection of basic linux tools)

[root@host ~]#  docker run busybox echo hi zarko 
Unable to find image 'busybox:latest' locally 
latest: Pulling from library/busybox
e2334dd9fee4: Pull complete
Digest: sha256:a8cf7ff6367c2afa2a90acd081b484cbded349a7076e7bdf37a05279f276bc12
Status: Downloaded newer image for busybox:latest
hi zarko

[root@host ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS  NAMES

[root@host ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS  NAMES
00dae245f506        busybox             "echo hi zarko"     10 seconds ago      Exited (0) 8s ago          wonderful_stonebraker

[root@host ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              be5888e67be6        3 weeks ago         1.22MB

Ubuntu interactive container

Run image ubuntu in container, -i = connect to container's stdin, -t = start pseudo terminal
[root@host ~]#  docker run -it ubuntu bash 
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
d51af753c3d3: Pull complete
fc878cd0a91c: Pull complete
6154df8ff988: Pull complete
fee5db0ff82f: Pull complete
Digest: sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7
Status: Downloaded newer image for ubuntu:latest

root@15647ff74996:/#   {note, we are in Ubuntu now } 

root@15647ff74996:/# cat /etc/debian_version
bullseye/sid
From host we see container is running.
[root@chost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS        PORTS  NAMES
15647ff74996        ubuntu              "bash"              8 minutes ago       Up 8 minutes         elastic_murdock
I run 'sleep' in container and PID is 15, but on the host, the PID is 30824.
root@50615ff83b68:/# sleep 120 &
[1] 15
root@50615ff83b68:/# pgrep sleep
15

[root@host ~]# pgrep sleep
30824
#  docker run -h MYCONT -ti ubuntu bash 
root@MYCONT:/# ls -la /root
total 8
drwx------ 2 root root   37 Apr 23 11:09 .
drwxr-xr-x 1 root root    6 May 11 16:13 ..
-rw-r--r-- 1 root root 3106 Dec  5 14:39 .bashrc
-rw-r--r-- 1 root root  161 Dec  5 14:39 .profile

root@ZZ:/etc# cp resolv.conf resolv.conf~

[root@host ~]#  docker diff 8f5f913b9f62 
C /etc
A /etc/resolv.conf~

[root@host ~]# docker logs 8f5f913b9f62 --follow

Non-interactive container

[root@host ~]# docker run -h MyCont -it ubuntu bash

root@MyCont:/# read escape sequence  {{Detach with ctrl P + ctrl Q}} 
[root@host ~]#

[root@host ~]#  docker attach wizardly_gagarin 
root@MyCont:/#   {{back to container}} 

[root@host ~]#  docker inspect wizardly_gagarin --format {{.NetworkSettings.IPAddress}} 
172.17.0.2

Images

[root@host ~] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              1d622ef86b13        2 weeks ago         73.9MB
busybox             latest              be5888e67be6        3 weeks ago         1.22MB

Create new container from image

root@MyCont:# echo  "Acquire::http::Proxy \"http://proxy-fqdn:80\";" > /etc/apt/apt.conf.d/proxy.conf
root@MyCont:# cat /etc/apt/apt.conf.d/proxy.conf
Acquire::http::Proxy "http://www-proxy.comp.com:80";

root@MyCont:# apt-get update
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [107 kB]
... shortened..
Fetched 13.6 MB in 21s (649 kB/s)
Reading package lists... Done

root@MyCont:# apt-get install nano
root@MyCont:# which nano
/usr/bin/nano

[root@host~]# docker diff wizardly_gagarin
C /root
... shortend ..
A /usr/bin/rnano

[root@host~]#  docker commit wizardly_gagarin ubuntu_nano 
sha256:3e71536eccec4f482c55cc08f7eb22813ffde3de844e57a8f953286c8df86dff

[root@host ~]# docker images
REPOSITORY   TAG      IMAGE ID        CREATED          SIZE
ubuntu_nano  latest   3e71536eccec    4 minutes ago    96MB  {bigger size then basic ubuntu image
ubuntu       latest   1d622ef86b13    2 weeks ago      73.9MB

[root@host ~]#  docker history -H ubuntu_nano 
[root@host ~]#  docker run -it 3e71536eccec 

root@b4aa90ca0c6a:/# which nano
/usr/bin/nano   {yes, new image is Ubuntu + nano} 

Build image with Dockerfile (plus CMD, ENTRYPOINT)

We want to: Build an image (run command where Dockerfile is), tag as ubuntu_figlet:
[root@host~]#  docker build -t ubuntu_figlet . 
Sending build context to Docker daemon  3.584kB
Step 1/6 : FROM ubuntu
 ---> 1d622ef86b13
-- shortened --
Step 6/6 : CMD figlet Hi You
 ---> Using cache
 ---> 9674d8f662e8
Successfully built 9674d8f662e8
Successfully tagged uguntu_figlet:latest

[root@host~]#  docker images 
REPOSITORY          TAG         IMAGE ID            CREATED             SIZE
uguntu_figlet       latest      9674d8f662e8        30 minutes ago      96.3MB

[root@host ~]# docker run ubuntu_figlet
 _   _ _  __   __
| | | (_) \ \ / /__  _   _
| |_| | |  \ V / _ \| | | |
|  _  | |   | | (_) | |_| |
|_| |_|_|   |_|\___/ \__,_|

[root@host ~]# docker run ubuntu_figlet hostname
dd5db05d4665    {{ so 'figlet' default command is overwritten with hostname of container}} 
# build from this base image
FROM ubuntu

# LABEL is key-value pair.
LABEL description="This is test"

# RUN run command and commit result, during build time
# Use RUN to build your image by adding layers on top of initial RO image
RUN echo "Acquire::http::Proxy \"http://proxy-fqdn:80\";" > /etc/apt/apt.conf.d/proxy.conf \
    && apt-get update && apt-get install figlet

# Only one CMD in Dockerfile. If more, only last CMD takes effect.
# CMD defines default command and/or arguments, they are overwritten if 'docker run' is used with other arguments
CMD /var

# Use ENTRYPOINT to define container with specific executable.
ENTRYPOINT ["ls", "/etc"]
[root@host docker-project]#  docker build -t entrypoint-test . 

# cd /tmp
[root@host tmp]#  docker run -it entrypoint-test 
/bin/sh
/etc:  {from ENTRYPOINT} 
hostname      logrotate.d  skel           libaudit.conf  host.conf
..
kernel        security     profile        group          adduser.conf
ld.so.conf.d  selinux      rmt            gshadow

/var: {from CMD} 
lib  log  cache  backups  local  mail  opt  spool  tmp  run  lock

[root@host tmp]#  docker run -it entrypoint-test /dev 
/dev:  {overwritten by CLI argument} 
console  fd    mqueue  ptmx  random  stderr  stdout  urandom
core     full  null    pts   shm     stdin   tty     zero

/etc:  {from ENTRYPOINT is still present}
adduser.conf            environment  ld.so.conf.d   pam.d        security
..
emacs                   ld.so.conf   pam.conf       rmt

Build image with Dockerfile (using COPY)

[root@host docker-project]#  docker build -t cont-1 . 

[root@home docker-project]#  docker inspect cont-1 --format {{.Author}} 
ZD, z.d@comp.ca

[root@host docker-project]#  docker run cont-1 
==============================
Hallo to test Docker container.
==============================

Web server and ports

[root@host ~]#  docker run -d --publish-all nginx 
6e97b619b0f953de417bf05e3451972e7ea3de596af43477d1e7a926955b2dc4

[root@host ~]#  docker ps -l 
CONTAINER ID   IMAGE  COMMAND                  CREATED     STATUS    PORTS                 NAMES
6e97b619b0f9   nginx  "nginx -g 'daemon of…"   50sec ago   Up 50sec  0.0.0.0:32769->80/tcp  determined_davinci

[root@some-other-host]  curl http://host:32769 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
~~ shortened ~~
</html> 

[root@host ~]#  docker port determined_davinci 80 
0.0.0.0:32769

[root@host ~]#  docker run -d -p 9999:80 nginx 
ea25e2ff49f135e61a67de489aa9962e4916b2cdc6c62ae72a9f214c1324cab6

[root@host ~]# docker ps -l 
CONTAINER ID        IMAGE     COMMAND                  CREATED    STATUS    PORTS                 NAMES
ea25e2ff49f1        nginx     "nginx -g 'daemon of…"   4 sec ago  Up 3 sec  0.0.0.0:9999->80/tcp  serene_meitner
[root@host ~]# docker port serene_meitner 80 
0.0.0.0:9999

Networks

#  docker run -d -P nginx 
0a5daec65fbc44485c78c6dafd8a86b1a4088333b4c77e8fd0f5af61686a0ccf

# docker ps
CONTAINER ID        IMAGE      COMMAND                  CREATED     STATUS         PORTS                   NAMES
0a5daec65fbc        nginx      "nginx -g 'daemon of…"   3 sec ago   Up 3 seconds   0.0.0.0:32770->80/tcp   sharp_mendeleev

#  ip addr s docker0 
3: docker0:  mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:0a:2e:ff:4c brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aff:fe2e:ff4c/64 scope link
       valid_lft forever preferred_lft forever

#  docker inspect sharp_mendeleev --format {{.NetworkSettings.IPAddress}} 
172.17.0.2

# ping 172.17.0.2 -c 3
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.033 ms
#  docker run -d -P --net none nginx 
58595db01a81e78713301f4ece6fa52bb377fd22a77f2991e8401493052e0fc7

# docker inspect  58595db01a81 --format {{.NetworkSettings.IPAddress}}
{no output, no IP} 
[root@host ~]#  docker run -it --net host oraclelinux 

#  cat /etc/oracle-release
Oracle Linux Server release 7.8  {we're in container ol7.8, since host is ol8.2} 

# ip addr s eth0  {container can see host's eth0} 
2: eth0:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:21:f6:11:11:b6 brd ff:ff:ff:ff:ff:ff
    inet 10.147.24.49/22 brd 10.147.27.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::221:f6ff:fe11:11b6/64 scope link noprefixroute
       valid_lft forever preferred_lft forever


[root@host ~] #  docker inspect 3ba3ff4301be --format {{.HostConfig.NetworkMode}} 
host
[root@host ~]#  docker network create qa_lab 
2489c60363dcfa20f81880b84d38c098dd808e9db7f9d89a85b060aed54eba07

[root@host ~]#  docker network list 
NETWORK ID          NAME                DRIVER              SCOPE
1bb1acc8d5a7        bridge              bridge              local
6b93f7024a35        host                host                local
44629a77b0c7        none                null                local
2489c60363dc        qa_lab              bridge              local

[root@host ~]#  docker network inspect qa_lab 
[
    {
        "Name": "qa_lab",
        "Id": "2489c60363dcfa20f81880b84d38c098dd808e9db7f9d89a85b060aed54eba07",
        "Created": "2020-05-16T19:44:29.560249937-07:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.22.0.0/16",
                    "Gateway": "172.22.0.1"
                }
 ~ shortened 
]

[root@host ~]#  docker run -dit --net qa_lab --name ol oraclelinux 
1d54750260996947d22fcb9fa43fd31569bd916aa4cad11baad410c932bc6a0a

[root@host ~]#  docker run -dit --net qa_lab --name fedora fedora 
3d1bb06d612d2361444ce57f2660ec4a64f3ec962f48d83724e36562afcd281a

[root@host ~]#  docker attach fedora 

[root@3d1bb06d612d /]# cat /etc/hosts
127.0.0.1       localhost
172.22.0.3      3d1bb06d612d

[root@host ~]#  docker attach ol 

[root@1d5475026099 /]# cat /etc/hosts
127.0.0.1       localhost
172.22.0.2      1d5475026099

[root@1d5475026099 /]# ping 172.22.0.3
PING 172.22.0.3 (172.22.0.3) 56(84) bytes of data.
64 bytes from 172.22.0.3: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 172.22.0.3: icmp_seq=2 ttl=64 time=0.060 ms

[root@host ~]# docker inspect fedora --format {{.NetworkSettings.Networks.qa_lab.IPAddress}} 
172.22.0.3
[root@host ~]# docker inspect ol --format {{.NetworkSettings.Networks.qa_lab.IPAddress}} 
172.22.0.2

[root@host ~]# docker network connect bridge ol

[root@host ~]#  docker attach ol 

[root@1d5475026099 /]# cat /etc/hosts
127.0.0.1       localhost
172.22.0.2      1d5475026099
172.17.0.2      1d5475026099

[root@host ~]# docker inspect ol --format {{.NetworkSettings.Networks.qa_lab.IPAddress}}
172.22.0.2 
[root@host ~]# docker inspect ol --format {{.NetworkSettings.Networks.bridge.IPAddress}}
172.17.0.2 

Volumes

Volume is directory/file that's not part of container (its Union File System), it can be defined in three ways.
Examples are using httpd (Apache) image, index.html file is in container's /usr/local/apache2/htdocs directory.

Back to the main page