cleaning up docker

It’s been a while since I used Docker on my machine so I decided to clean things up. When I launched Docker, it prompted me to upgrade. Half a gig but easy to get that out of the way at least.

Then I ran “docker images” and was reminded that I haven’t done a good job of keeping this clean. I had:

  • the original docker-whale play
  • a bunch of experiments from when I didn’t know what I was doing (some of which have unnamed layers so I don’t even know what they are)
  • some Java 9 early access edition stuff
  • following along with the “Kubernetes in Action” book when I was the Technical Development Editor
  • a lab I went to

Note: i’m not sure if any of this is a good way of doing things. But it worked for me.

Deleting the images the slow way

Yuck. I decided to delete all the images. For some, it was easy. Just run “docker rmi <imageHash>”.

For some, I got

Error response from daemon: conflict: unable to delete xxx (cannot be forced) - image has dependent child images

I also tried running “docker rmi $(docker images -a -q)” to delete all the images. This deleted some, but gave the same dependent child images error.

Great, I don’t know what they are.  Luckily, StackOverflow had a command to find the children.

for i in $(docker images -q)
do
    docker history $i | grep -q xxx && echo $i
done | sort -u

I also got:

Error response from daemon: conflict: unable to delete xxx (must be forced) - image is referenced in multiple repositories

For these, it was just a matter of running “docker -rmi –force xxx.”

Deleting the images the fast way

I deleted the rest of the images with:

“docker rmi –force $(docker images -a -q)”

Containers and volumes

I did a far better job of cleaning these up!

docker ps -a

docker volume ls

DevNexus 2018 – Deep Dive into Dockerfiles

Title: Deep Dive into Dockerfiles
Speakers: Raju Gandhi

For more blog posts, see the DevNexus 2018 live blogging table of contents


Benefits

  • read only/immutable
  • unique identifier

What docker files do under the covers

# Start interactive linux container
docker run -it ubuntu:17.10 bash

# create new image (read only file system)
docker commit containerName demo
# list images (local only)
docker images
docker run -it demo bash
# list running images
docker ps

Docker files – like a build file for docker
# base image
FROM ubuntu:17.19
# run command at command line
RUN touch java

Layers

  • each command creates an intermediate image with a new name
  • better to merge commands so less layers ex:
    RUN command a \
    command b
  • But need the code to be readable
  • same idea as git commits – a tree where points to parent and knows the diff
  • each OS has limit of number of layers. On Mac, this is 127
  • if run apt-get install and then apt-get clean-all, you’ve increased the image size. Two layers, one to add and one to delete. Want both in same step so doesn’t increase size by whole file size twice!.

Cache

  • every Docker pull leverages the cache
  • RUN touch java and RUN touch    java have different sha hashes and are considered different commands. So cache not used
  • Do not write RUN ls -l or other commands for debugging. You can just open an interactive bash into that layer to debug
  • Put commands that move files towards the bottom. This allows for more reuse of the common parts of the image.

General notes

Don’t install sshd. Can use docker commands for that.

Dockerfile

  • FROM
    • Implies “ancestry” – what is parent image and what will you be inheriting. Ex: running whoami when inheriting jenkins image, it prints “jenkins”. This means you have to look at lineage if having permission issues. May have to keep looking at parent and grandparent and …
    • Must be first line
    • Consider starting with Ubuntu and building yourself so know what is in there. Less security implications if do it yourself.
    • Rare, but can write “FROM scratch” to start over. Usually only used for go code.
    • While multiple FROMs are allowed, it is a terrible idea. Diamond problem; they can conflict on basic things like version of Ubuntu.
    • Do not use “latest” tag. Use an exact tag. “LATEST” is a lie. It is just a tag. You can tag versions after LATEST. If you don’t switch the tag, it is still the old one.
    • Inspect ancestors for USER, PORT, ENV, VOLUME, LABEL, etc
    • docker inspect – lets you see what is in there. Recommends tracing by hand to be more thorough.
  • RUN
    • Don’t run commands that upgrade the OS. Use a later base image instead.
    • Group commands with && so not adding more layers
    • Beware of cache. If write RUN apt-get update, it will cache the result and not run again. If use && for all related commands, they are unique.
    • Want each command on separate line starting with && and ending with \ (except first and last). This makes it easy to git diff to see what changed
  • ADD/COPY
    • Combine COPY and RUN
    • Much of RUN applies
  • LABELS
    • Use lots
    • Labels can read ENV variables
    • Can use image (compile) or container (run) scope
    • Ex: build number, scm location
    • Just like RUN, can merge all LABELS in one line. Just end line with \ to continue (no && like when running)
    • To read label, do docker inspect and “grep Labels”
  • ENTRYPOINT/CMD
    • Both can run commands
    • Both can take command raw (xxx abc) or as array of command/args ([“xxx”, “abc”]). Better to use array so bash doesn’t have to fork
    • Run [“/bin/bash” “-c” “xxx” “$arg”] if need variable expansion to get bash involved
    • Better to have a shell script and call it with ENTRYPOINT. That way gets treated as a shell script without having to call bash. It is also easier to read since you aren’t writing bash as strings. The cost is that you add a layer because you have to copy the script into the image.
    • docker stop id – takes 10 seconds because need to send a signal to PID 1 and have it stop

Other practices

  • Create you own ancestry/hierarchy.
  • Containers are changing how we ship software. Don’t put Oracle’s JDK in an image and then put on dockerhub. Legal issues.
  • Consider using multi-stage builds.
    • FROM x as y …. FROM z – different scopes – binary executable vs build tools.
    • “as y” is what makes it a multi-stage build. Everything until the next “FROM” is not part of the container. The “FROM” without an “as” creates what will go in the container.
    • Only contains what need. Not the build tools. Smaller image. Less “extra” stuff.

My take

This was really good. It was clear if you didn’t know much about Docker while still having good info for those somewhat familiar. For the best practices, some people were taking notes on what to fix! I actually realized that I applied one of his anti-patterns to a Java compare program I wrote. I need to go and add some new lines in my generator for ease of diff! More gray/black background for code though. Blue (comments) on a dark background is hard to read.

Also, it is great that DevNexus has tables in the first few rows. Reward for sitting up front! (I chose to blog on my Mac as I expected to type a lot of commands).

JavaOne – Docker, Kubernetes & Open Shift

“Project Jigsaw – Integration with Tools”

Speaker: Marek Jelen & Diogenes Rettori

Sponsored session by RedHat [I didn’t know they had sponsored sessions; I asked if they applied to JavaOne or Oracle Open World and they said neither; they paid. I was curious why they were JavaOne and yet had laptops provided by Oracle. That explains why three sessions of this class were offered.]

For more blog posts from JavaOne, see the table of contents


Can do self paced tutorials in cloud install at https://learn.openshift.com

[Nice assortment of shipping container pictures on the screen as he reviews what Docker/Kubernetes are for and why this matters. A bit of preaching to the choir here…]

“Very diverse community of contributors” The top six contributors are all from Google and RedHat. (except one who move to Microsoft) [sounds more like a strong partnership than a diverse community]

Open Shift and Kubernetes

  • OpenShift is an enterprise version of Kubernetes with extra stuff.
  • OpenShift 3.6 in lab
  • Can use kubectl with Open Shift cluster
  • OpenShift sometimes uses own version of Kubernetes objects and wrap others
  • RHEL (red hat enterprise linux) has master and nodes.
  • Nodes used to be called minions.
  • Works with cloud and non-cloud deployments
  • OpenShift adds Developer CLI,, Admin CLI, web console, REST APIs, creating an image from source, authentication and users/groups from LDAP, Also wrap namespace in a project and more

Workshop

bit.ly/javaoneworkshop

http://content-workshop.apps.javaone3.gce.pixy.io/index.html#/workshop/training/module/install

I’ve read about and played with Kubernetes. I didn’t realize OpenShift was Kubernetes with different commands.

Concepts from lab

  • pod – smallest deployable unit
  • service – group of pods
  • replication controllers – ensure correct number of pods exist
  • deployment configuration – how should be configured
  • horizonal pod auto scaler – monitors CPU and scales. See here
  • route – so external clients can access
  • service account – non-user account, get one by default

Commands in lab

  • oc login url – to login
  • oc get x – basic info
  • oc get x -o yaml – more detail in yaml
  • oc describe service x – even more detail
  • oc scale –replicas=x y – or can click up arrow in UI
  • oc delete pod x – to delete
  • oc expose service x – to create route
  • oc logs x – view logs
  • oc policy add-role-to-user view -z default – grant access to view for default user
  • oc policy add-role-to-user view user1 – grant access to view for user1

In UI

  • Add project > docker
  • Change number of replicas with up/down arrows once expand overview
  • View logs by clicking “…” on overview
  • Add project > catalog > python – use source to image so can go straight from github source code

Real world

  • 18% adults have anxiety problems
  • “not all anxiety is bad” depends on the task; issue on more complex/unfamiliar/difficult tasks
  • 20% of downtime is caused by tech failure or natural disasters. Rest caused by people
  • batch size – amount of features in a release

A/B Deployment demo

  • installed Node.JS app directly from github
  • then created a separate app from github. (so now have two apps in open shift)
  • edit route in open shift console to divide traffic between the two services. can choose percentages/weights
  • changed RAM; did rolling deployment so old one stays up until new one is ready

My take: We immediately had a problem because the laptop was setup differently than the lab; odd. not a big deal to type ./oc instead of oc. But that seems easy for them to have fixed in the VM. then the project we were supposed to switch to we were already on. then it says to login with your email vs the name we were given. I’ll stop commenting on the differences now, but this clearly wasn’t written for or tested for JavaOne. It even refers to “in the morning session” for how you find out what a pod is. I asked and they said this was written to be a full day of training. So glad that I’ve already read about Kubernetes and was able to follow it anyway. I like when they showed how to do the same task in both the UI and at the command line

[I did 9/12 of the labs. It wasn’t that they were bad or long. I was having trouble focusing. It’s 100% self paced and I wasn’t asking any questions. Or learning much. A small percentage of the lab is the UI and the rest I’ve done already with raw Kubernetes. So decided to use the remaining time to check twitter posts about other parts of the conference. I didn’t leave because the last 20 minutes are a demo of something I haven’t seen so wanted to see that.]