= Docker = Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications. http://www.zdnet.com/article/what-is-docker-and-why-is-it-so-darn-popular/ Developers can use Docker to pack, ship, and run any application as a lightweight, portable, self sufficient LXC container that can run virtually anywhere. In a nutshell, here's what Docker can do for you: It can get more applications running on the same hardware than other technologies; it makes it easy for developers to quickly create, ready-to-run containered applications; and it makes managing and deploying applications much easier. http://en.wikipedia.org/wiki/LXC LXC (Linux Containers) is an operating system–level virtualization method for running multiple isolated Linux systems (containers) on a single control host. LXC provides operating system-level virtualization through a virtual environment that has its own process and network space, instead of creating a full-fledged virtual machine. == Tutorial == https://www.docker.com/tryit https://hub.docker.com/ https://docs.docker.com/installation https://docs.docker.com/articles/basics/ == Windows install == https://docs.docker.com/installation/windows/ The Docker Engine uses Linux-specific kernel features, so to run it on Windows we need to use a lightweight virtual machine (vm). docker run hello-world == Docker SSH container Ubuntu == https://docs.docker.com/examples/running_ssh_service/ In bootDocker create ~/ssh/Dockerfile : {{{ # sshd # # VERSION 0.0.2 FROM ubuntu:14.04 MAINTAINER Sven Dowideit RUN apt-get update && apt-get install -y openssh-server RUN mkdir /var/run/sshd RUN echo 'root:screencast' | chpasswd RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"] }}} * docker build -t eg_sshd . * docker run -d -P --name test_sshd eg_sshd * docker ps -l * ssh root@127.0.0.1 -p49153 # password screencast * sudo docker stop test_sshd # stop container test_sshd == Install jdk8 in trusty == * apt-get install software-properties-common * add-apt-repository ppa:openjdk-r/ppa -y * apt-get update * apt-get install openjdk-8-jdk Dockerfile {{{ FROM ubuntu:14.04 RUN apt-get update && \ apt-get install -y traceroute openssh-server software-properties-common mongodb rabbitmq-server && \ add-apt-repository ppa:openjdk-r/ppa -y && \ apt-get update && \ apt-get install -y openjdk-8-jdk RUN mkdir /var/run/sshd RUN echo 'root:12345678' | chpasswd RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile EXPOSE 22 8080 8081 8082 5672 15672 27017 80 CMD ["/usr/sbin/sshd", "-D"] }}} = Install Docker CE slack 64 14.2 = * https://slackbuilds.org/repository/14.2/system/docker/ == Install go lang == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/development/google-go-lang.tar.gz tar xvzf google-go-lang.tar.gz cd google-go-lang wget https://storage.googleapis.com/golang/go1.10.1.src.tar.gz change slackbuild to use 1.10.1 ./google-go-lang.SlackBuild installpkg /tmp/google-go-lang-1.9.5-x86_64-1_SBo.tgz go --version In ~/.bashrc export GOPATH="$HOME:/usr/share/gocode" go help buildmode go get golang.org/x/tools/cmd/godoc remove support to gcc-go ! /usr/lib64/go1.10.1/go/bin/ /usr/lib64/go1.10.1/go/bin/go version # in ~/.bashrc export PATH="$PATH:/usr/lib64/go1.10.1/go/bin/" }}} == Install docker-proxy == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/system/docker-proxy.tar.gz tar xvzf docker-proxy.tar.gz cd docker-proxy wget https://github.com/docker/libnetwork/archive/1b91bc9/libnetwork-1b91bc94094ecfdae41daa465cc0c8df37dfb3dd.tar.gz ./docker-proxy.SlackBuild installpkg /tmp/docker-proxy-20180314_1b91bc9-x86_64-1_SBo.tgz }}} == Install tini == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/system/tini.tar.gz tar xvzf tini.tar.gz cd tini wget https://github.com/krallin/tini/archive/949e6fa/tini-949e6facb77383876aeff8a6944dde66b3089574.tar.gz ./tini.SlackBuild installpkg /tmp/tini-0.13.0_949e6fa-x86_64-1_SBo.tgz }}} == Install libseccomp == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/libraries/libseccomp.tar.gz tar xvzf libseccomp.tar.gz cd libseccomp wget https://github.com/seccomp/libseccomp/archive/v2.3.3/libseccomp-2.3.3.tar.gz ./libseccomp.SlackBuild installpkg /tmp/libseccomp-2.3.3-x86_64-1_SBo.tgz }}} == Install runc == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/system/runc.tar.gz tar xvzf runc.tar.gz cd runc wget https://github.com/opencontainers/runc/archive/v1.0.0-rc5/runc-1.0.0-rc5.tar.gz ./runc.SlackBuild installpkg /tmp/runc-1.0.0_rc5-x86_64-1_SBo.tgz }}} == Install containerd == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/system/containerd.tar.gz tar xvzf containerd.tar.gz cd containerd wget https://github.com/containerd/containerd/archive/v1.0.2/containerd-1.0.2.tar.gz ./containerd.SlackBuild installpkg /tmp/containerd-1.0.2-x86_64-1_SBo.tgz }}} == Install docker == {{{ cd /tmp wget https://slackbuilds.org/slackbuilds/14.2/system/docker.tar.gz tar xvzf docker.tar.gz cd docker wget https://github.com/docker/docker-ce/archive/v18.03.0-ce/docker-ce-18.03.0-ce.tar.gz ./docker.SlackBuild installpkg /tmp/docker-18.03.0-x86_64-1_SBo.tgz Added option --userland-proxy=false in /etc/rc.d/rc.docker variable DOCKER_OPTS="--userland-proxy=false" cd /etc/rc.d sh rc.docker status sh rc.docker start }}} == Docker image with SSH Ubuntu Xenial 16.04 == Adapted from https://docs.docker.com/engine/examples/running_ssh_service/ Dockerfile: {{{ # https://docs.docker.com/engine/examples/running_ssh_service/ FROM ubuntu:16.04 RUN apt-get update && apt-get install -y openssh-server RUN mkdir /var/run/sshd RUN echo 'root:screencast' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile RUN useradd userx RUN echo 'userx:userx' | chpasswd EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"] }}} Steps: {{{ docker build -t docker_test . docker run -d -P --name test_container1 docker_test docker ps -a ssh root@127.0.0.1 -p32771 useradd userx echo 'userx:userx' | chpasswd ssh userx@127.0.0.1 -p32771 docker container stop test_container1 docker container rm test_container1 docker image rm docker_test }}} == Install Docker in Ubuntu Xenial (16.04.4) vagrant box == {{{#!highlight bash mkdir tmp cd tmp vagrant init ubuntu/xenial64 vagrant up vagrant ssh # inside the box with user vagrant sudo bash apt-get update apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - apt-key fingerprint 0EBFCD88 add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" apt-get update apt-get install docker-ce docker run hello-world usermod -aG docker exit exit #login again with vagrant ssh # as user vagrant docker run hello-world # install java and maven apt-get install openjdk-8-jdk apt-get install maven }}} == Commands == {{{#!highlight bash docker ps -a # showall containers docker system prune -a # clean system docker ps -a | awk '//{print $1}' | grep -v "CONTAINER" | xargs -i sh -c 'docker stop {};docker rm {}' # clear all containers docker build -t acme_app . # build image from docker file docker run -P -p 8080:80 -d acme_app # run dettached container from image acme_app mapping port 8080 to port exposed 80 }}} == Docker DNS server == * https://docs.docker.com/v17.09/engine/userguide/networking/configure-dns/ {{{ As of Docker 1.10, the docker daemon implements an embedded DNS server which provides built-in service discovery for any container created with a valid name or net-alias or aliased by link. So you should not assume the way the files such as /etc/hosts, /etc/resolv.conf are managed inside the containers and leave the files alone and use the following Docker options instead. Note: The DNS server is always at 127.0.0.11. }}} == Docker container based on GCC image == {{{#!highlight bash docker run -it gcc /bin/bash docer ps -a docker exec -it /bin/bash # inside container cat /etc/os-release apt-get update }}} == Docker playground - cherrypy == * https://www.katacoda.com/courses/docker/playground === Dockerfile === {{{#!highlight bash # docker build -t image_cherrypy . # build image from Dockerfile # docker run -P -p 8080:80 -d image_cherrypy # touch cherrypytest.wsgi # links http://localhost/add/3/4 # curl -X POST -d "{\"name\":\"jkl\"}" http://localhost/hellojson --header "Content-Type:application/json" FROM ubuntu:16.04 RUN apt-get update && apt-get install -y python libapache2-mod-wsgi apache2 vim links net-tools nano curl wget RUN wget https://pypi.python.org/packages/source/C/CherryPy/CherryPy-3.2.4.tar.gz RUN cp CherryPy-3.2.4.tar.gz /tmp RUN cd /tmp && tar xvzf CherryPy-3.2.4.tar.gz RUN cd /tmp/CherryPy-3.2.4 && python setup.py build && python setup.py install RUN mkdir -p /var/www/htdocs/cherrypytest/static # copy cherrypytest.wsgi from where the Dockerfile is COPY cherrypytest.wsgi /var/www/htdocs/cherrypytest/cherrypytest.wsgi RUN echo "Static Test" > /var/www/htdocs/cherrypytest/static/a.txt RUN echo "\nServerName localhost\nDocumentRoot \"/var/www/htdocs/cherrypytest\"\nWSGIScriptAlias / /var/www/htdocs/cherrypytest/cherrypytest.wsgi\n\nRequire all granted\n\n" > /etc/apache2/sites-available/000-default.conf RUN echo "#!/bin/sh\n service apache2 start \n tail -f /var/log/apache2/error.log" > /start.sh EXPOSE 80 CMD ["sh","/start.sh"] }}} === cherrypytest.wsgi === {{{#!highlight python import sys sys.stdout = sys.stderr import cherrypy cherrypy.config.update({'environment': 'embedded'}) class HelloWorld(object): @cherrypy.expose def index(self): return "Hello World CherryPy!!!!" @cherrypy.expose def add(self,param1,param2): return str( int(param1)+int(param2) ) @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() def hellojson(self): # curl -X POST -d "{\"name\":\"jkl\"}" http://localhostcherrypytest/hellojson --header "Content-Type:application/json" inj = cherrypy.request.json return {"message": "hello world " + inj['name'] } hello = HelloWorld() #static dir confx={'/static': {'tools.staticdir.on':True , 'tools.staticdir.dir':'/var/www/htdocs/cherrypytest/static' }} application = cherrypy.Application(hello, script_name=None, config=confx) }}} == Docker - openjdk8 - hello == === Main.java === {{{#!highlight java //Main.java public class Main{ public static void main(String args[]){ System.out.println("Hello docker!"); } } }}} === Dockerfile === {{{#!highlight bash FROM openjdk:8-alpine RUN mkdir -p /usr/src/hello_docker COPY . /usr/src/hello_docker WORKDIR /usr/src/hello_docker RUN javac Main.java CMD ["java", "Main"] }}} === Execute === {{{#!highlight bash # build image hello-docker-image using Dockerfile docker build -t hello-docker-image . # run the container based on the image docker run -it --rm --name hello-docker hello-docker-image }}} == Docker - openjdk 8 - hello - maven == * mkdir -p src/main/java/com/example/artifactX === pom.xml === {{{#!highlight xml 4.0.0 com.example artifactX jar 0.0.1 artifactX http://maven.apache.org maven-assembly-plugin 2.4 jar-with-dependencies com.example.artifactX.Main make-assembly package single }}} === src/main/java/com/example/artifactX/Main.java === {{{#!highlight java package com.example.artifactX; //Main.java public class Main{ public static void main(String args[]){ System.out.println("Hello docker!"); } } }}} === Dockerfile === {{{#!highlight bash FROM openjdk:8-alpine RUN apk add maven RUN mkdir -p /usr/src/hello_maven_docker COPY . /usr/src/hello_maven_docker WORKDIR /usr/src/hello_maven_docker RUN mvn clean install CMD ["java", "-jar" , "target/artifactX-0.0.1-jar-with-dependencies.jar"] }}} === Execute === {{{#!highlight bash docker build -t hello-maven-docker-image . docker run -it --rm --name hello-maven-docker hello-maven-docker-image }}} == springboot-test == mkdir springboot-test cd springboot-test/ mkdir -p src/main/java/hello/ mkdir -p src/main/resources/templates/ === Dockerfile === {{{ }}} === pom.xml === {{{#!highlight xml 4.0.0 hello test-spring-boot 0.1.0 org.springframework.boot spring-boot-starter-parent 1.4.0.RELEASE org.springframework.boot spring-boot-starter-thymeleaf hello.Application org.springframework.boot spring-boot-maven-plugin spring-milestone http://repo.spring.io/libs-release spring-milestone http://repo.spring.io/libs-release }}} === src/main/java/hello/GreetingController.java === {{{#!highlight java package hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.ArrayList; @Controller public class GreetingController { private final Logger logger = LoggerFactory.getLogger(GreetingController.class); public GreetingController(){ logger.debug("Greeting controller created."); } @RequestMapping("/greeting") // http://localhost:8080/greeting?name=nnnn public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) { logger.info("Greeting endpoint called."); model.addAttribute("name", name); return "greeting"; } @RequestMapping(value="/dummy",produces="application/json") @ResponseBody // http://localhost:8080/dummy public List dummy(){ List list= new java.util.ArrayList(); Dummy dummy = new Dummy(); dummy.setFieldA("AAA"); dummy.setFieldB("CCC"); list.add(dummy); Dummy dummy2 = new Dummy(); dummy2.setFieldA("AAA2"); dummy2.setFieldB("CCC2"); list.add(dummy2); return list; } } }}} === src/main/java/hello/Application.java === {{{#!highlight java package hello; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Bean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ComponentScan @EnableAutoConfiguration public class Application { private static Logger logger; public static void main(String[] args) { logger = LoggerFactory.getLogger(Application.class); logger.info("Starting application"); SpringApplication.run(Application.class, args); } } }}} === src/main/java/hello/ThreadTimer.java === {{{#!highlight java package hello; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import java.text.MessageFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; @Component public class ThreadTimer extends Thread { private int delaySeconds; private Logger logger; private boolean running; private Object monitor=new Object(); private ArrayList subscribers; //@Autowired //WaitThread waitThread; public ThreadTimer() { this.logger = LoggerFactory.getLogger(ThreadTimer.class); logger.info("Created instance of " + this.getClass().getSimpleName()); this.running = true; this.delaySeconds = 5 * 1000; this.setName(this.getClass().getSimpleName() + "_" + this.getName()); this.subscribers = new ArrayList(); } public void addSubscriber(Object subscriber){ this.subscribers.add(subscriber); } @PostConstruct public void init() { logger.info("Starting the thread"); this.start(); } @Override public void run() { while (running) { try { Thread.sleep(this.delaySeconds); logger.info("Delay " + this.getClass().getSimpleName()); for(Object o: this.subscribers){ synchronized(o){ o.notify(); } } } catch (InterruptedException e) { logger.info("ThreadTimer interrupted exception:" + e.getMessage() ); } catch (Exception e) { e.printStackTrace(); logger.info("ThreadTimer exception:" + e.getMessage() ); stopRunning(); } } logger.info("Exited " + this.getClass().getSimpleName()); } public void startRunning() { this.running = true; } public void stopRunning() { this.running = false; } public void destroy(){ logger.info("Called destroy"); this.stopRunning(); this.interrupt(); } } }}} === src/main/java/hello/WaitThread.java === {{{#!highlight java package hello; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.text.MessageFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @Component public class WaitThread extends Thread { private Logger logger; private boolean running; private Object monitor; @Autowired ThreadTimer timerThread; public WaitThread() { this.logger = LoggerFactory.getLogger(WaitThread.class); logger.info("Created instance of " + this.getClass().getSimpleName()); this.running = true; this.setName(this.getClass().getSimpleName() + "_" + this.getName()); this.monitor=new Object(); } @PostConstruct public void init() { this.timerThread.addSubscriber(this); logger.info("Starting the thread"); this.start(); } public void run() { while (running) { try { synchronized(this){ this.wait(); logger.info("Notification received."); } } catch (InterruptedException e) { logger.info("ThreadTimer interrupted exception:" + e.getMessage() ); } catch (Exception e) { logger.info("WaitThread exception:" + e.getMessage() ); stopRunning(); } } logger.info("Exited " + this.getClass().getSimpleName()); } public void startRunning() { this.running = true; } public void stopRunning() { this.running = false; } public void destroy(){ logger.info("Called destroy"); this.stopRunning(); this.interrupt(); } } }}} === src/main/java/hello/Dummy.java === {{{#!highlight java package hello; public class Dummy{ private String fieldA; private String fieldB; public Dummy(){ } public String getFieldA(){ return fieldA; } public String getFieldB(){ return fieldB; } public void setFieldA(String arg){ fieldA = arg; } public void setFieldB(String arg){ fieldB = arg; } } }}} === src/main/resources/templates/greeting.html === {{{#!highlight xml Getting Started: Serving Web Content

}}} === src/main/resources/application.properties === {{{#!highlight bash logging.file=/tmp/testout.log }}} === src/main/resources/logback-spring.xml === {{{#!highlight xml ${filelog} %date{ISO8601} [%thread] %-5level %logger{35} - %msg%n /tmp/greet.log %date{ISO8601} [%thread] %-5level %logger{35} - %msg%n %yellow(%date{ISO8601}) %green([%thread]) %highlight(%-5level) %cyan(%logger{35}) - %white(%msg%n) }}} === Execute === * touch Dockerfile * touch pom.xml * mkdir -p src/main/java/hello/ * mkdir -p src/main/resources/templates/ * touch src/main/java/hello/GreetingController.java * touch src/main/java/hello/Application.java * touch src/main/java/hello/ThreadTimer.java * touch src/main/java/hello/WaitThread.java * touch src/main/java/hello/Dummy.java * touch src/main/resources/templates/greeting.html * touch src/main/resources/application.properties * touch src/main/resources/logback-spring.xml * mvn clean install * java -Dfilelog=/tmp/out.log -jar target/test-spring-boot-0.1.0.jar * http://localhost:8080/greeting