Task:
Need to optimize a Containerfile (Dockerfile) file so least amount of command layers (layer = sequences/list of commands) to prep for this Containerfile (Dockerfile) to be a parent to be used with child deployments.
Tasks:
- Reduce LABEL calls to 1 call
- Reduce RUN calls as close to 1 as possible
- Create an image of the parent Containerfile to be used as source to generate child images with default content from /src.
Child Deployment Tasks:
- Create child derivative version of Dockerfile
- Create deployment using the new Dockerfile
Lab Environment:
Git Repo: git.ocp4.mindwatering.net/mwapp/dockerbuild.git
Branch: dev
Username: developer
Password: mydevpassword
Workstation: mydev1.mindwatering.net
Username and Password: <same as repo>
Workstation Working Directory: ~/dockerbuild/
OCP4/OKD: <your OKD on port 6443>
Username and password: <same as repo>
Project: mwapp
Steps:
1. Create working directory (if not exists) and clone:
a. Create working folder:
$ ssh developer@mydev1.mindwatering.net
<enter pwd>
$ cd ~/
$ mkdir mwapp
$ cd mwapp
$ pwd
/home/developer/mwapp
b. Clone the repo:
Note:
- For repo requiring authentication with keys, append " login" or append username, like: git clone http ... developer@git.ocp4.mindwatering.net/mwapp/dockerbuild.git
- Alternately, setup private/public keys if an internal repo.
$ git clone https://git.ocp4.mindwatering.net/mwapp/dockerbuild.git login
<enter username/password prompts>
c. Enter inside repo:
$ ls
dockerbuild
$ cd dockerbuild
d. Switch to correct dev branch:
Note:
- Process: git clone --> git fetch origin --> git switch --> git pull (if someone else might be working while doing all this)
- Use git checkout before git version 2.23.0
- Use git switch starting with git version 2.23.0
$ git fetch origin
<outputs the branches e.g. master, staging, dev, etc.>
$ git switch dev
<confirm switched>
$ git pull
<confirm any updates>
2. Locate the Dockerfile, analyze, and update:
a. View Dockerfile and check for changes needed:
$ ls
...
Dockerfile
...
README.md
$ cp Dockerfile zBackupDockerfile
$ cat Dockerfile
FROM registry.mindwatering.net/ubi9/ubi-minimal:latest
LABEL version="1.0"
LABEL description = "UBI Minimal with Python3 installed"
LABEL owner = "MW IT"
LABEL maintainer = "Tripp Black"
user root
RUN microdnf install -y python3
RUN microdnf clean all
RUN mkdir -p /app
RUN echo "Hello container world - Version 1.0" > /app/index.html
ENV DOCROOT=/app
EXPOSE 8080
USER 1001
WORKDIR /app
CMD [python3", "-m", "http-server", "8080"]
b. Update Dockerfile:
Notes:
- Need to update the LABELs so in one pass
- Need to update the RUNs so in one pass
- Need to add an ONBUILD COPY of src/ from the /app folder so that child based builds on parent image can be performed
- Besides ONBUILD COPY, we can include specific ONBUILD RUN commands to install different additional software for each child image build
$ vi Dockerfile
FROM registry.mindwatering.net/ubi9/ubi-minimal:latest
LABEL version="1.0" \
description = "UBI Minimal with Python3 installed" \
owner = "MW IT" \
maintainer = "Tripp Black"
user root
RUN microdnf install -y python3 && \
microdnf clean all && \
mkdir -p /app && \
echo "Hello container world - Version 1.0" > /app/index.html
ENV DOCROOT=/app
ONBUILD COPY src/ $(DOCROOT)
EXPOSE 8080
USER 1001
WORKDIR /app
CMD [python3", "-m", "http-server", "8080"]
<esc> :wq (to save)
3. Push back up to git (Github):
$ git status
<view that one file has been updated - should be red color because not added to push yet>
$ git add .
$ git status
<view that one file is now green color because added>
$ git commit -m "optimize Dockerfile for child builds and reduce layers"
<confirm message: 1 file changed>
$ git push
<authenticate with username and password>
Username for ...: developer
Password for ...: mydevpassword
<confirm success messge>
4. Verify Containerfile (Dockerfile) with podman:
a. Login:
$ podman login -u developer
<enter password at prompt>
Password: mydevpassword
<verify login says Succeeded>
b. Create an image:
Notes:
- Image name is podman local image from which to create the main app (parent) build and app deploy in OCP/OKD
- Will run from the base folder of the local copy of the repo just pushed (using the single . (dot/period) for this folder
IMPORTANT:
- Podman defaults to the OCI image format which does not support ONBUILD instructions. Use --format docker to switch podman to the docker image format. Otherwise, messages will be presented saying the ONBUILD is being skipped.
- Use the -t flag to specify the name of the parent image "base"
- Use the -f flag or leave out and just specify the filename for the Containerfile (Dockerfile) file/script to use
$ pwd
/home/developer/mwapp/dockerbuild
$ podman build --format docker -t mwappimage-v1 .
<wait for build: blobs --> run of Dockerfile --> LABELS --> USER --> RUN (with package install lines) --> ENV DOCROOT --> ONBUILD COPY (will be ignored - must use docker format) --> EXPOSE --> USER (1001) --> WORKDIR --> CMD (python http run) --> Successfully tagged localhost/mwappimage-v1:latest>
c. Review image and image size:
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
...
localhost/myappimage-v1 latest ab12cd34... 12 seconds ago 160 MB
...
5. Deploy mwapp (parent) to OCP/OKD:
a. Create project (namespace) if not created already:
$ oc new-project mwapp
<confirm created>
Verify:
$ oc project
<confirm says Using project 'mwapp'>
b. Create app from the pushed repo's edited Dockerfile:
$ oc new-app --name=mwapp https://git.ocp4.mindwatering.net/mwapp/dockerbuild
<wait, confirm creating resources completed, confirm success message>
- Confirm build progress and that app deploys:
$ oc get po
<view pods confirm build exists for mwapp app>
NAME READY STATUS RESTARTS AGE
...
mwapp-1-build 0/1 Init:1/2 0 8s
...
$ oc get builds
<confirm running or completed>
NAME TYPE FROM STATUS STARTED DURATION
...
mwapp-1 Docker Git@abc123 Running 12 seconds ago
...
$ oc get bc
<confirm exists>
NAME TYPE FROM LATEST
...
mwapp Docker Git 1
...
$ oc get po
<view pods confirm build completed and mwapp app running>
NAME READY STATUS RESTARTS AGE
...
mwapp-1-build 0/1 Completed 0 45s
mwapp-1234abcd-12ab34 1/1 Running 0 18s
...
c. Expose app:
$ oc expose svc/mwapp
<confirm route exposed>
$ oc get route
<view app routes, and note fqdn route for mwapp>
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
...
mwapp mwapp-container-build.apps.ocp4.mindwatering.net mwapp 8080-tcp None
...
d. Confirm app loads in browser:
web browser --> url field: mwapp-container-build.apps.ocp4.mindwatering.net
<confirm web page says: Hello container world - Version 1.0>
e. Confirm parent image:
$ oc get images | grep mwapp
sha256:123...abc image-registry.openshift-image-registry.svc:5000/container-build/mwapp@sha265:123...abc
Notes:
- The parent image is: image-registry.openshift-image-registry.svc:5000/container-build/mwapp
- The parent image is now ready for child deployments.
- The child Dockerfile will need only the FROM line.
6. Deploy a child deployment using the parent's image specifying the /src folder.
Note:
- Typically, the child apps would be either a different git repo/app, or would be a different branch of same repo.
- Use git checkout -b to create a new branch from the current branch dev. Or from any branch add the branch to use as the source at the end - git checkout -b <newbranch> <existingbranch>
a. Confirm still in the git local repo and create the new branch:
$ pwd
/home/developer/mwapp/dockerbuild
$ git checkout -b devchild dev
b. Push the branch to the git (Github) repo:
Note:
- git push -u ensures the created branch on the remote repo is linked to our new branch just created.
$ git push -u origin devchild
<confirm>
c. Update the Containerfile (Dockerfile) for child deployments:
Note:
- Use the image URL from the end of step 5 above.
$ vi Dockerfile
FROM image-registry.openshift-image-registry.svc:5000/container-build/mwapp
<esc> :wq (to save)
d. Create new build in OCP/OKD:
$ oc new-build --name=mwapp-child --strategy=docker --binary=true
<wait>
e. Confirm build:
$ oc get bc
<confirm child exists>
NAME TYPE FROM LATEST
...
mwapp Docker Git 1
mwapp-child Docker Binary 0
...
f. Build child using the local devchild branch Containerfile:
Note:
- Use --follow to watch the build
$ oc start-build mwapp-child --from-dir=.
<wait>
g. Confirm build:
$ oc get po
<view pods confirm build exists for mwapp app>
NAME READY STATUS RESTARTS AGE
...
mwapp-1-build 0/1 Completed 0 10m45s
mwapp-1234abcd-12ab34 1/1 Running 0 10m18s
...
mwapp-child-1-build 0/1 Completed 0 60s
...
$ oc get builds
<confirm running or completed>
NAME TYPE FROM STATUS STARTED DURATION
...
mwapp-1 Docker Git@abc123 Completed 8 minutes ago 30s
...
mwapp-child-1 Docker Binary@def456 Completed 35 seconds ago 15s
...
h. Create a mwapp-child app from the new mwapp-child build:
$ oc new-app mwapp-child --name=mwapp-child
<wait>
i. Confirm running and expose:
$ oc get po
<view pods confirm build completed and mwapp-child app running>
NAME READY STATUS RESTARTS AGE
...
mwapp-1-build 0/1 Completed 0 11m45s
mwapp-1234abcd-12ab34 1/1 Running 0 11m18s
...
mwapp-child-1-build 0/1 Completed 0 45s
mwapp-child-5678abcd-90ab12 1/1 Running 0 10s
...
j. Expose app:
$ oc expose svc/mwapp-child
<confirm route exposed>
$ oc get route
<view app routes, and note fqdn route for mwapp>
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
...
mwapp-child mwapp-child-container-build.apps.ocp4.mindwatering.net mwapp 8080-tcp None
...
k. Confirm output of child's HTML page:
$ cat ./src/index.html
Hello world from child container - Version 1.0
l. Confirm app loads in browser:
web browser --> url field: mwapp-child-container-build.apps.ocp4.mindwatering.net
<confirm web page says: Hello world from child container - Version 1.0>
previous page
|