Docker

Overview

Docker’s central function is to build, ship, and run software in any location that has Docker. To the end user, Docker is a command-line program that they run.

Terminology

Docker Client The docker command used to control most of the Docker workflow and talk to remote Docker servers.

Docker Server The docker command run in daemon mode. This turns a system into a Docker Server that can have containers deployed, launched, and torn down via a remote client.

Docker Image Docker images consist of one or more filesystem layers and some important metadata that represent all the files required to run a Dockerized application. A single Docker image can be copied to numerous hosts. A container will typically have both a name and a tag. The tag is generally used to identify a particular release of an image. To launch a container, you must either download a public image or create your own.

Docker Container A Docker Container is a runtime instance of an Image. Containers run until the app they are executing exits.

Image Registry Docker images are stored in image registries. The most common registry is Docker Hub.

Image Repository Image registries contain multiple image repositories. In turn, image repositories can contain multiple images.

Docker Containers

Container Lifecycle

  • Create and start a new Container
    • docker container run --name percy -it ubuntu /bin/bash
  • Stop the running Container
    • docker container stop percy
      • You can use the container’s name or ID with the docker container stop command.
  • Restart the Container
    • docker start percy
  • Attach to restarted Container
    • docker container exec -it percy bash
  • Stop the running Container
  • Remove the Container
    • docker container rm percy

Any data you store in the container will be stored between restarts.

Docker Hub

Pushing a Local Image to Docker Hub

  • Find the ID of the Image you want to push using docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
flyingpig           latest              eae7f2b2857a        4 minutes ago       81.4MB
openjdk             8u131-jre-alpine    d5b43d97f41b        16 months ago       81.4MB
  • Login to Docker Hub
    • docker login
  • Tag your image
    • docker tag eae7f2b2857a koraytugay/flyingpig:initial-tag
  • Push your image
    • docker push koraytugay/flyingpig

Reference: Pushing and Pulling to and from Docker Hub

Pulling from Docker Hub

  • docker pull <repository>:<tag>
    • docker pull koraytugay/flyingpig:initial-tag
    • If you do not specify an image tag after the repository name, Docker will assume you are referring to the image tagged as latest.
  • For official repositories, you do not need to specify repository
    • docker pull ubuntu

Useful Commands

  • Listing Docker Images: docker image ls
  • Listing Docker Containers: docker container ls
  • Stopping and removing a Container: docker container stop ContainerID - docker container rm ContainerID
    • You can enter first few digits of the ID as long as it is unique, Docker will know which Container to stop / remove

Useful Links

Play Docker

Docker on Mac

Docker for Mac will not give you the Docker Engine running natively on the Mac OS Darwin kernel. Behind the scenes, the Docker daemon is running inside a lightweight Linux VM. It then exposes the daemon and API to your Mac environment. This means you can open a terminal on your Mac and use the regular Docker commands.

Examples

Ubuntu Hello World

  • docker pull ubuntu
  • Use the -it parameter to run the container in interactive mod
  • docker container run -it ubuntu
    • A minimal running ubuntu will start and shell will be available

Java Hello World

It would also be possible to deploy the source file to the image and compile it when the container starts. In this example however the source file is compiled and the class file is deployed to the container.

  • Create a HelloWorld.java file and compile it
  • DockerFile
FROM openjdk:8u131-jre-alpine
ENV HW_HOME=/opt/hello-world
ADD HelloWorld.class $HW_HOME/
WORKDIR $HW_HOME
ENTRYPOINT ["java", "HelloWorld"]
  • At this point you should have the following files in a directory
.
├── ./Dockerfile
├── ./HelloWorld.class
└── ./HelloWorld.java
  • Build the image
    • docker build -t hello-world .
  • Run the image
    • docker run hello-world

Node Hello World

  • server.js
const http = require('http');

const port = 4000;

const server = http.createServer(function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
});

server.listen(port);

console.log('Server running at http://localhost:' + port);
  • package.json
{
  "main": "server.js"
}
  • Dockerfile
FROM node
COPY . /src
RUN cd /src && npm install
EXPOSE 4000
CMD ["node", "/src/server.js"]
  • Build the image
    • docker build -t hello-world .
  • Build a Container from this Image and start the Container
    • docker run -p 4001:4000 hello-world
      • Syntax for the ports is: host-port:container-port
  • Verify the server is up and running
    • localhost:4001
      • If localhost does not work, you may need to find the IP assigned to the Container
  • Stop the Container
    • Find the Container ID
      • docker container ls
    • docker stop {ContainerID}

Reference: Docker + Node "Hello World" Example

2 Stage Build Example With Maven

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>biz.tugay</groupId>
    <artifactId>bare-maven-project</artifactId>
    <packaging>jar</packaging>

    <version>1.0-SNAPSHOT</version>

    <name>bare-maven-project</name>
    <url>http://www.tugay.biz</url>

    <build>
        <finalName>bare-maven-project</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>biz.tugay.bareMaven.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

Dockerfile

FROM maven:3.5-jdk-8 AS build  
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean install

FROM gcr.io/distroless/java
COPY --from=build /usr/src/app/target/bare-maven-project.jar /usr/app/bare-maven-project.jar  
ENTRYPOINT ["java","-jar","/usr/app/bare-maven-project.jar"]  

Reference: How to dockerize maven project?

Cheat Sheet

  • Delete all stopped containers docker rm $(docker ps -a -q)
  • Delete all images docker rmi $(docker images -q)

Further Resources