2.1 Controlling containers:Building a website monitor

  • Create detached and interactive containers
  • List containers on your system
  • view container logs
  • Stop and restart containers
  • Reattach a terminal to a container
  • Detach from an attached container

    2.1.1 Creating and starting a new container

    1. docker run --detach \
    2. --name web nginx:latest
    —detach: started the program in the background, the short form is “-d”

The following command installs and run a mailer that will work for this example:

  1. docker run -d \
  2. --name mailer \
  3. dockerinaction/ch2_mailer

2.1.2 Running interactive containers

Runing interactive programs in Docker requires that you bind parts of your terminal to the input or output of a running container

  1. docker run --interactive --tty \
  2. --link web:web \
  3. --name web_test \
  4. busybox:1.29 /bin/sh

—interactive(or -i): tells Docker to keep the standart input stream open for the container even if no terminal is attached
—tty: tells Docker to allocate a virtual terminal for the container, which will allow you to pass signals to the container
/bin/sh: you specified the program to run inside the container that is a shell program called sh.

From this shell, you can run a command to verify that your web server is running correctly:

  1. wget -O - http://web:80/

image.png
you can shut down this interactive container by typing “exit”

This is a monitoring agent that will test the web server as you did in the preceding example and send a message with the mailer if the web server stops

  1. docker run -it \
  2. --name agent \
  3. --link web:insideweb \
  4. --link mailer:insidemailer \
  5. dockerinaction/ch2_agent

the container will test the web container every second and print a message like the following:

  1. System up.

hold the ctrl + P + Q. After doing so, you’ll be returned to the shell for your host computer. Do not stop the progra; otherwise, the monitor will stop checing the web server

2.1.3 Listing, stopping, restarting, and viewing output of containers

docker ps: check which containers are currently running

  1. docker ps

image.png
Running the command will display the following information about each running container:

  • The container ID
  • The image used
  • The command exected in the container
  • The time since the container was created
  • The duration that the container has been running
  • The network ports exposed by the container
  • The name of the container

The next three commands will restart each container by using the container name:

  1. docker restart web
  2. docker restart mailer
  3. docker restart agent

examine the logs of the web container

  1. docker logs web

image.png
For completeness, you should examine the log output for mailer and agent as well:

  1. docker logs mailer
  2. docker logs agent

The logs for mailer should look something like this:

  1. CH2 Example Mailer has started

The logs for agent should look something like this:

  1. System up

The docker stop command tells the program with PID 1 in the container to halt. Use it in the following commands to test the system:

  1. docker stop web
  2. docker logs mailer

image.png

2.2 Solved problems and the PID namespace

A PID namespace is a set of unique numbers that identify process.
Docker creates a new PID namespace for each container by default. A container’s PID namespace isolates processes in that container from processes in other containers.
PID 1 might refer to an init system process such as runit or supervisord. In a different container, PID 1 might refer to a command shell such as bash.

  1. docker run -d --name namespaceA \
  2. busybox:1.29 /bin/sh -c "sleep 30000"
  3. docker run -d --name namespaceB \
  4. busybox:1.29 /bin/sh -c "nc -l 0.0.0.0 -p 80"
  5. docker exec namespaceA ps
  6. docker exec namespaceB ps

image.png

You can optionally create containers without their own PID namespace. You can try this yourself by setting the “—pid” flag on “docker create” or “docker run” and setting the value to host

  1. docker run --pid host busybox:1.29 ps

You can see it in action by tring to run two copies of NGINX in the same container:

  1. docker run -d --name webConflict nginx:latest
  2. docker logs webConflict
  3. docker exec webConflict nginx -g 'daemon off;'

The last command should display output like this:
image.png

It’s a great example of a conflict problem that Docker simplifies and solves. Run each in a different container, like this:

  1. docker run -d --name webA nginx:latest
  2. docker logs webA
  3. docker run -d --name webB nginx:latest
  4. docker logs webB

Here are some common conflict problems:

  • Two programs want to the same network port
  • Two programs use the same temporary filename, and file locks are preventing that
  • Two programs want to use different versions of a globally installed library.
  • Two programs want to use the same PID file.
  • A second program you installed modified an environment variable that another program uses. Now the first program breaks.
  • Multiple process are competing for memory or CPU time.

2.3 Eliminating metaconflicts: Building a website farm

image.png

2.3.1 Flexible container identification

If a situation arises in which the name of a container needs to change, you can always rename the container with the “docker rename “ command :

  1. docker rename webid webid-old
  2. # Creates another container named "webid"
  3. docker run -d --name webid nginx

you could use the previous ID with a stop or exec command:

  1. docker exec \
  2. 7cb5d2b9a7eab87f07182b5bf58936c9947890995b1b94f412912fa822a9ecb5 \
  3. echo hello
  4. docker stop \
  5. 7cb5d2b9a7eab87f07182b5bf58936c9947890995b1b94f412912fa822a9ecb5

because of the first 12 characters of this ID wouldn’t be a collision, so the previous two commands could be written like this:

  1. docker exec 7cb5d2b9a7ea ps
  2. docker stop 7cb5d2b9a7ea

The “docker create” command is similar to “docker run”, the primary difference being that the container is created in a stopped state:

  1. docker create nginx

If you’re using a Linux command shell such as sh or bash, you can assign that result to a shell variable and use it again later:

  1. CID=$(docker create nginx:latest)
  2. echo $CID

Both the docker run and docker create commands provide another flag to write the ID of a new container to a known file:

  1. docker create --cidfile /tmp/web.cid nginx
  2. cat /tmp/web.cid

if you want to get the truncated ID of the last created container, you can use this:

  1. CID=$(docker ps --latest --quiet)
  2. echo $CID
  3. CID=$(docker ps -l -q)
  4. echo $CID

2.3.2 Container state and dependencies

the new system might look something like this:

  1. MAILER_CID=$(docker run -d dockerinaction/ch2_mailer)
  2. WEB_CID=$(docker create nginx)
  3. AGENT_CID=$(docker create --link $WEB_CID:insideweb \
  4. --link $MAILER_CID:insidemailer \
  5. dockerinaction/ch2_agent)

The docker container management commands to move between states annotate each transition
image.png
To see all the containers( including those in the created state), use the -a option:

  1. docker ps -a
  1. # The containers need to be started in reverse order of their dependency chain
  2. docker start $WEB_CID
  3. docker start $AGENT_CID

2.4 Building environment-agnostic systems

Docker has three specific features to help build environment-agnostic systems:

  • Read-only filesystems
  • Environment variable injection
  • Volumes

    2.4.1 Read-only filesystems

    To get started working on your client’s system, create and start a container from the WordPress image by using the —read-only flag:
    1. docker run -d --name wp --read-only \
    2. wordpress:5.0.0-php7.2-apache
    The following command will print true if the container named wp is running, and false otherwise:
    1. docker inspect --format "{.State.Running}" wp
    This command should simply output false
    To determine why, examine the logs for the container:
    1. docker logs wp
    image.png
    1. docker run -d --name wp_writable wordpress:5.0.0-php7.2-apache
    Now let’s check where Apache changed the container’s filesystem with the docker diff command:
    1. docker container diff wp_writable
    image.png
    1. docker run -d --name wp2 \
    2. --read-only \
    3. # Mounts a writable directory from the host
    4. -v /run/apache2/ \
    5. # Provides container an in-memory temp filesystem
    6. --tmpfs /tmp \
    7. wordpress:5.0.0-php7.2-apache
    image.png
    WordPress also has a dependency on a Mysql database
    1. docker run -d --name wpdb \
    2. -e MYSQL_ROOT_PASSWORD=ch2demo \
    3. mysql:5.7
    create a different WordPress container that’s linked to this new database container:
    1. docker run -d --name wp3 \
    2. --link wpdb:mysql \
    3. # Directs traffic from host port 8000 to container port 80
    4. -p 8000:80 \
    5. --read-only \
    6. -v /run/apache2/ \
    7. --tmpfs /tmp \
    8. wordpress:5.0.0-php7.2-apache
    An updated version of the script you’ve been working on should look like this: ```shell

    !/bin/sh

    DB_CID = $(docker create -e MYSQL_ROOT_PASSWORD=root mysql:5.7) docker start $DB_CID MAILER_CID = $(docker create dockerinaction/ch2_mailer) docker start $MAILER_CID

WP_CID = $(docker create —link $DB_CID:mysql -p 80 \ —read-only -v /run/apache2/ —tmpfs /tmp \ wordpress:5.0.0-php7.2-apache)

docker start $WP_CID

AGENT_CID = $(docker create —link $WP_CID:insideweb \ —link $MAILER_CID:insidemailer \ dockerinaction/ch2_agent)

docker start $AGENT_CID

  1. <a name="surVW"></a>
  2. ## 2.4.2 Environment variable injection
  3. To see environment variable injection in action, use the following command:
  4. ```shell
  5. docker run --env MY_ENVIRONMENT_VAR="this is a test" \
  6. busybox:1.29 \
  7. env

2.5 Building durable containers

2.5.1 Automatically restarting containers

2.5.1 Using PID 1 and init systems

a full LAMP(Linux, Apache, MySQL, PHP) stack inside a single container. That created this way use supervisord to make sure that all the related processes are kept running

  1. docker run -d -p 80:80 --name lamp-test tutum/lamp

you can see which processes are running inside this container by using the docker top command:
image.png
Find the PID on the row for apache2 and then insert that for in the following command:

  1. docker exec lamp-test kill <PID>
  1. # uses "cat" as the entrypoint
  2. docker run --entrypoint="cat" \
  3. wordpress:5.0.0-php7.2-apache \
  4. # passes the full of the default entrypoint script as an argument to cat
  5. /usr/local/bin/docker-entrypoint.sh

2.6 Cleaning up

To remove a container from your computer, use the docker rm command

  1. docker rm wp
  1. docker run --rm --name auto-exit-test busybox:1.29 echo Hello World
  2. docker ps -a

Doing so will automatically remove the container as soon as it enters the exited state

  1. docker rm -vf $(docker ps -a -q)