Creation of a Base Image for other Docker Images


I prefer Ubuntu over any other distribution out there. Seems to be the least amount of hassle to get anything done with it over any other distro I’ve used and I’ve used a lot of them both professionally and for my home use.  For that reason I base all my other images on Ubuntu and towards that end I have a base Ubuntu image that I maintain and occasionally modify that all other images I create for my own use are based on.

I can just hear someone asking “what about Alpine?”   Yes I know a lot of Docker people prefer Alpine and it is a good distro.  My odgita with it came when I was trying to create a derived image with it where I had to build the application on the image build I had a hassle getting the right combination of libraries, utilities and other stuff causing me to pull out what little hair I have left.

Ubuntu “just works” from my perspective and certainly some applications seem to thrive there better than other distributions of Linux.   Don’t even talk to me about Windows anything because I don’t do Windows.

Why even create a custom base image?

My first answer would be because I am a bit of a control freak.  But that is certainly not a complete answer.  I go by the theory  “If I have to do it twice I’m automating it.”  My custom image consists of things that are going to be in common with other images derived from the base image.

What’s in this image?

For all my derived images I wan to have the following items:

  • Puppet agent;  this gives me the flexibility of using Puppet to make tweaks to application configurations over the lifespan of the application as well as items such as repository configurations, SSH/SSL keys etc.
  • Nagios NRPE server.  Allows me to monitory up/down status of the application.

Simple enough list but this will also allow me to use Jenkins later on to make updates to the installed packages on the image itself when the Ubuntu team publishes their updates.

Where can I get this image?

I have an account on Docker Hub as userid saltycowdawg.  The image you would be interested in would be saltycowdawg/ubuntu:latest.  I have not yet updated tags to this image preferring to use the “latest” tag for now.  Once I consider this ready for a new tag I plan to increment the semantic version of the image as well as the “latest” tag.

I also maintain my own Git repository (even though I’m a fan of Bit Bucket, it’s that whole control freak thing) and the base URL is which is going to eventually move to which will be documented here when it does. The current Git repository was an experiment originally and has outlived its experimental stage.  The full URL for the image definitions is here.

Keep in mind this image and its derivitives are meant to be used with Kubernetes but can also be used with “docker-compose” as well.

Getting down to business

I will just plunge right in and show the Dockerfile this image has been built with:



### Base Ubuntu package that has the Puppet agent already installed but
### not initialized.
### -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
FROM ubuntu:18.04
LABEL MAINTAINER Peter L. Berghold &lt;;
# Arguments that can be overridden
ARG   OPTDIRPATH=/opt/docker-utils
# Environmental variables to be passed to the container that are set
# by the values in the argument list.
# Make sure the OS is up to date
RUN apt-get update &amp;&amp; \
    apt-get -y dist-upgrade
# Install some much needed stuff before we go further
RUN export DEBIAN_FRONTEND=noninteractive &amp;&amp; \
    apt-get -y --no-install-recommends install wget curl  \
    libterm-ui-perl libterm-readline-perl-perl apt-utils 
# Load the Puppet deb repository package
RUN cd /tmp &amp;&amp; wget --quiet ${PUPPET_DPKG} &amp;&amp; \
    dpkg -i $(basename ${PUPPET_DPKG} ) &amp;&amp; \
    rm -rf $(basename ${PUPPET_DPKG})
# This is the main build 
RUN apt-get update &amp;&amp; export DEBIAN_FRONTEND=noninteractive &amp;&amp; \
    apt-get -y install --no-install-recommends openssh-server openssh-client \
               openssl puppet-agent \
               nagios-nrpe-server  ntp &amp;&amp; \
	       apt-get -y remove curl wget &amp;&amp; \
	       apt-get -y autoremove  &amp;&amp; \
	       rm -rf /var/lib/apt/lists/* &amp;&amp; \
               rm -fr /etc/localtime &amp;&amp; \
               ln -s /usr/share/zoneinfo/America/New_York /etc/localtime &amp;&amp; \
               echo "America/New_York" &gt; /etc/timezone &amp;&amp; \
	       mkdir -vp ${OPTDIRPATH}/init.d
COPY docker-inits/ ${OPTDIRPATH}/init.d/

This image definition is very definitely going to be subject to change. For instance there are a few more ARG variables I plan to add such as which Timezone.  Currently I am being chauvinistic in my choice of America/New_York because that’s where I live.


413 Errors with a Nginx Ingress

To begin with let me explain that I run a Kubernetes cluster using Digital Ocean’s Managed Kubernetes offering. So far I am very pleased with it. Very easy to set up and is more economical than offerings from other cloud providers.   At some point in the not too distant future I plan to add a post about how to go about that along with some hints covering what I’ve done slightly different from the norm.

I started migrating all of my blogs from my own Docker cloud engine which I plan to retire soon once I migrate everything over.  One of those blogs is my cooking blog and once I did that I managed to run into an unexpected snag.

As I started uploading images to it I ran into a screen that informed me the upload was too large along with a “413” error from nginx itself. What to do?

I spent the better part of two hours researching this issue and decided to open a ticket with Digital Ocean to see if they had come across this issue and went to bed. Next morning I had a reply that referred me to an article that I had read already.  Slowly the light bulb turned on in my brain.  The solutions I found before all depended on how the Nginx ingress controller was deployed to the Kubernetes cluster.

Stepping back a bit

When I set up the Nginx ingress controller I did it with Helm/Tiller using one of their charts.  Worked so far but the default settings were the issue.  Knowing this I made a discovery.  If I modified each of the ingress YAML files for the individual blogs I could solve the issue.  Here is the ingress configuration for


apiVersion: extensions/v1beta1
kind: Ingress
  name: cowdawg-kitchens-ingress
  annotations: nginx cowdawg-kitchens-issuer "50m"
    - hosts:
      secretName: cowdawg-kitchens-issuer
  - host:
      - backend:
          serviceName: cowdawg-kitchens
          servicePort: 80

Let me call your attention to the line “ “50m””

That’s the line you need with the ingress loaded by Helm/Tiller.  Seems to be working fine now.


Copyright Devops — In the Trenches 2019
Tech Nerd theme designed by Siteturner