diff --git a/.gitignore b/.gitignore index 3ed4b64..79b5594 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ **/.DS_Store -*.xml diff --git a/attendees/cicd/docker-compose-gogs.yml b/attendees/cicd/docker-compose-gogs.yml deleted file mode 100644 index 30a8b73..0000000 --- a/attendees/cicd/docker-compose-gogs.yml +++ /dev/null @@ -1,8 +0,0 @@ -gogs: - image: gogs/gogs - container_name: gogs - volumes: - - /Users/arungupta/gogs:/data - ports: - - "10022:22" - - "10080:3000" diff --git a/attendees/cicd/docker-compose.yml b/attendees/cicd/docker-compose.yml deleted file mode 100644 index bb92bf4..0000000 --- a/attendees/cicd/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -gitlab: - image: gitlab/gitlab-ce:latest - # container_name: gitlab - ports: - - "8443:443" - - "8080:80" - - "2222:22" - volumes: - - /Users/arungupta/tmp/gitlab/config:/etc/gitlab - - /Users/arungupta/tmp/gitlab/logs:/var/log/gitlab - - /Users/arungupta/tmp/gitlab/data:/var/opt/gitlab - restart: always \ No newline at end of file diff --git a/attendees/cicd/docker-compose2.yml b/attendees/cicd/docker-compose2.yml deleted file mode 100644 index d8d15d7..0000000 --- a/attendees/cicd/docker-compose2.yml +++ /dev/null @@ -1,40 +0,0 @@ -postgresql: - image: sameersbn/postgresql:9.4-3 - environment: - - DB_USER=gitlab - - DB_PASS=password - - DB_NAME=gitlabhq_production - volumes: - - /Users/arungupta/tmp/gitlab/postgresql:/var/lib/postgresql -gitlab: - image: sameersbn/gitlab:7.14.1 - links: - - redis:redisio - - postgresql:postgresql - ports: - - "10080:80" - - "10022:22" - environment: - - TZ=US/Pacific - - SMTP_ENABLED=false - - SMTP_DOMAIN=www.example.com - - SMTP_HOST=smtp.gmail.com - - SMTP_PORT=587 - - SMTP_USER=mailer@example.com - - SMTP_PASS=password - - SMTP_STARTTLS=true - - SMTP_AUTHENTICATION=login - - GITLAB_TIMEZONE=Los_Angeles - - GITLAB_HOST=localhost - - GITLAB_PORT=10080 - - GITLAB_SSH_PORT=10022 - - GITLAB_EMAIL=admin@example.com - - GITLAB_EMAIL_REPLY_TO=noreply@example.com - - GITLAB_BACKUPS=daily - - GITLAB_BACKUP_TIME=01:00 - volumes: - - /Users/arungupta/tmp/gitlab/gitlab:/home/git/data -redis: - image: sameersbn/redis:latest - volumes: - - /Users/arungupta/tmp/gitlab/redis:/var/lib/redis \ No newline at end of file diff --git a/attendees/cicd/git-server/README.adoc b/attendees/cicd/git-server/README.adoc deleted file mode 100644 index 3ab79bd..0000000 --- a/attendees/cicd/git-server/README.adoc +++ /dev/null @@ -1,30 +0,0 @@ -= Install a Git Server - -== Start Services - -. All services can be started, in detached mode, by giving the command: - -+ - docker-compose up -d -+ -And this shows the output as: -+ - Creating git_serverdata... - Creating gitserver_git_dbdata_1... - Creating gitserver_git_db_1... - Creating git... -+ - -. Configure the installation -.. execute the following script -+ - ./install-gogs.sh -+ - -_example: ./install-gogs.sh 192.168.99.100 3000_ - -== Sign Up - -. Access to this URL: http://dockerhost:3000/user/sign_up -. Create an account and enjoy! -. Enjoy! :) diff --git a/attendees/cicd/git-server/docker-compose.yml b/attendees/cicd/git-server/docker-compose.yml deleted file mode 100644 index be9d250..0000000 --- a/attendees/cicd/git-server/docker-compose.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Gogs Image to manage git sources to build and release -git_server: - image: gogs/gogs - container_name: git - ports: - - "3000:3000" - - "10022:22" - volumes_from: - - git_serverdata - links: - - git_db:mysql - -git_serverdata: - image: busybox - container_name: git_serverdata - command: /bin/sh - volumes: - - /data - #Doesn't work for now version due to problem with filesystem - # - ./data/gogs/conf/app.ini:/data/gogs/conf/app.ini - -git_db: - image: mysql:5.6 - volumes_from: - - git_dbdata - ports: - - "3306:3306" - environment: - - MYSQL_ROOT_PASSWORD=supersecret - - MYSQL_DATABASE=gogs - - MYSQL_USER=mysql - - MYSQL_PASSWORD=mysql - -git_dbdata: - image: busybox - command: /bin/sh - volumes: - - /var/lib/mysql diff --git a/attendees/cicd/git-server/install-gogs.sh b/attendees/cicd/git-server/install-gogs.sh deleted file mode 100755 index 66ae1be..0000000 --- a/attendees/cicd/git-server/install-gogs.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -eu - -function installGogs(){ - local DOCKER_HOST_IP=$1 - local GOGS_HTTP_PORT=$2 - printf "\e[1;33m########################################\e[m\n" - printf "\e[1;33m# Install Gogs Server on: %s\e[m\n" "${DOCKER_HOST_IP}" - printf "\e[1;33m########################################\e[m\n" - - curl 'http://'${DOCKER_HOST_IP}':'${GOGS_HTTP_PORT}'/install' \ - -H 'Origin: null' -H 'Accept-Encoding: gzip, deflate' \ - -H 'Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4' \ - -H 'Upgrade-Insecure-Requests: 1' \ - -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36' \ - -H 'Content-Type: application/x-www-form-urlencoded' \ - -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' \ - -H 'Cache-Control: max-age=0' \ - -H 'Connection: keep-alive' \ - --data 'db_type=MySQL&db_host=mysql%3A3306&db_user=mysql&db_passwd=mysql&db_name=gogs&ssl_mode=disable&db_path=data%2Fgogs.db&app_name=Gogs%3A+Go+Git+Service&repo_root_path=%2Fhome%2Fgit%2Fgogs-repositories&run_user=git&domain='${DOCKER_HOST_IP}'&ssh_port=22&http_port='${GOGS_HTTP_PORT}'&app_url=http%3A%2F%2F'${DOCKER_HOST_IP}'%3A3000%2F&smtp_host=&smtp_from=&smtp_email=&smtp_passwd=&admin_name=&admin_passwd=&admin_confirm_passwd=&admin_email=' --compressed - - printf "Configuration OK." - printf "\e[1;33m# Go to http://%s:%s/user/sign_up\e[m\n" "${DOCKER_HOST_IP}" "${GOGS_HTTP_PORT}" - -} - -installGogs $1 $2 -open http://$1:$2/user/sign_up diff --git a/attendees/docker-compose.yml b/attendees/docker-compose.yml deleted file mode 100644 index e8d3410..0000000 --- a/attendees/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -mysqldb: - image: mysql - environment: - MYSQL_DATABASE: sample - MYSQL_USER: mysql - MYSQL_PASSWORD: mysql - MYSQL_ROOT_PASSWORD: supersecret -mywildfly: - image: arungupta/wildfly-mysql-javaee7 - links: - - mysqldb:db - \ No newline at end of file diff --git a/attendees/kubernetes/app-mysql-pod.yaml b/attendees/kubernetes/app-mysql-pod.yaml deleted file mode 100644 index b8884f3..0000000 --- a/attendees/kubernetes/app-mysql-pod.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: mysql-pod - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - containers: - - - name: mysql - image: mysql:latest - env: - - - name: "MYSQL_USER" - value: "mysql" - - - name: "MYSQL_PASSWORD" - value: "mysql" - - - name: "MYSQL_DATABASE" - value: "sample" - - - name: "MYSQL_ROOT_PASSWORD" - value: "supersecret" - ports: - - - containerPort: 3306 diff --git a/attendees/kubernetes/app-mysql-service.yaml b/attendees/kubernetes/app-mysql-service.yaml deleted file mode 100644 index 0cbb329..0000000 --- a/attendees/kubernetes/app-mysql-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql-pod - context: docker-k8s-lab diff --git a/attendees/kubernetes/app-wildfly-rc.yaml b/attendees/kubernetes/app-wildfly-rc.yaml deleted file mode 100644 index 303b63f..0000000 --- a/attendees/kubernetes/app-wildfly-rc.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: ReplicationController -metadata: - name: wildfly-rc - labels: - name: wildfly - context: docker-k8s-lab -spec: - replicas: 1 - template: - metadata: - labels: - name: wildfly - spec: - containers: - - name: wildfly-rc-pod - image: arungupta/wildfly-mysql-javaee7:k8s - ports: - - containerPort: 8080 \ No newline at end of file diff --git a/attendees/kubernetes/app.yaml b/attendees/kubernetes/app.yaml deleted file mode 100644 index 4ee8076..0000000 --- a/attendees/kubernetes/app.yaml +++ /dev/null @@ -1,64 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: mysql-pod - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - containers: - - - name: mysql - image: mysql:latest - env: - - - name: "MYSQL_USER" - value: "mysql" - - - name: "MYSQL_PASSWORD" - value: "mysql" - - - name: "MYSQL_DATABASE" - value: "sample" - - - name: "MYSQL_ROOT_PASSWORD" - value: "supersecret" - ports: - - - containerPort: 3306 ----- -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql-pod - context: docker-k8s-lab ----- -apiVersion: v1 -kind: ReplicationController -metadata: - name: wildfly-rc - labels: - name: wildfly - context: docker-k8s-lab -spec: - replicas: 1 - template: - metadata: - labels: - name: wildfly - spec: - containers: - - name: wildfly-rc-pod - image: arungupta/wildfly-mysql-javaee7:k8s - ports: - - containerPort: 8080 \ No newline at end of file diff --git a/attendees/kubernetes/create-script.sh b/attendees/kubernetes/create-script.sh deleted file mode 100644 index ef55fe3..0000000 --- a/attendees/kubernetes/create-script.sh +++ /dev/null @@ -1,3 +0,0 @@ -./cluster/kubectl.sh --v=5 create -f ../../attendees/kubernetes/app-mysql-pod.yaml -./cluster/kubectl.sh --v=5 create -f ../../attendees/kubernetes/app-mysql-service.yaml -./cluster/kubectl.sh --v=5 create -f ../../attendees/kubernetes/app-wildfly-rc.yaml diff --git a/attendees/kubernetes/delete-script.sh b/attendees/kubernetes/delete-script.sh deleted file mode 100644 index 992e9a9..0000000 --- a/attendees/kubernetes/delete-script.sh +++ /dev/null @@ -1,3 +0,0 @@ -./cluster/kubectl.sh --v=5 delete -f ../../attendees/kubernetes/app-wildfly-rc.yaml -./cluster/kubectl.sh --v=5 delete -f ../../attendees/kubernetes/app-mysql-service.yaml -./cluster/kubectl.sh --v=5 delete -f ../../attendees/kubernetes/app-mysql-pod.yaml diff --git a/chapters/docker-basics.adoc b/chapters/docker-basics.adoc deleted file mode 100644 index 3e60991..0000000 --- a/chapters/docker-basics.adoc +++ /dev/null @@ -1,143 +0,0 @@ -## Docker Basics - -*PURPOSE*: This chapter introduces the basic terminology of Docker. - -[quote, docs.docker.com/] -Docker is a platform for developers and sysadmins to develop, ship, and run applications. Docker lets you quickly assemble applications from components and eliminates the friction that can come when shipping code. Docker lets you get your code tested and deployed into production as fast as possible. - -Docker simplifies software delivery by making it easy to build and share images that contain your application’s entire environment, or _application operating system_. - -**What does it mean by an application operating system ?** - -Your application typically require a specific version of operating system, application server, JDK, database server, may require to tune the configuration files, and similarly multiple other dependencies. The application may need binding to specific ports and certain amount of memory. The components and configuration together required to run your application is what is referred to as application operating system. - -You can certainly provide an installation script that will download and install these components. Docker simplifies this process by allowing to create an image that contains your application and infrastructure together, managed as one component. These images are then used to create Docker containers which run on the container virtualization platform, provided by Docker. - -**Main Components of Docker** - -Docker has three main components: - -. __Images__ are *build component* of Docker and a read-only template of application operating system. -. __Containers__ are *run component* of Docker, and created from, images.Containers can be run, started, stopped, moved, and deleted. -. Images are stored, shared, and managed in a __registry__, the *distribution component* of Docker. The publically available registry is known as Docker Hub (available at http://hub.docker.com). - -In order for these three components to work together, there is *Docker Daemon* that runs on a host machine and does the heavy lifting of building, running, and distributing Docker containers. In addition, there is *Client* that is a Docker binary which accepts commands from the user and communicates back and forth with the daemon. - -.Docker architecture -image::docker-architecture.png[] - -Client communicates with Daemon, either co-located on the same host, or on a different host. It requests the Daemon to pull an image from the repository using `pull` command. The Daemon then downloads the image from Docker Hub, or whatever registry is configured. Multiple images can be downloaded from the registry and installed on Daemon host. Images are run using `run` command to create containers on demand. - -**How does a Docker Image work?** - -We've already seen that Docker images are read-only templates from which Docker containers are launched. Each image consists of a series of layers. Docker makes use of union file systems to combine these layers into a single image. Union file systems allow files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system. - -One of the reasons Docker is so lightweight is because of these layers. When you change a Docker image—for example, update an application to a new version— a new layer gets built. Thus, rather than replacing the whole image or entirely rebuilding, as you may do with a virtual machine, only that layer is added or updated. Now you don't need to distribute a whole new image, just the update, making distributing Docker images faster and simpler. - -Every image starts from a base image, for example `ubuntu`, a base Ubuntu image, or `fedora`, a base Fedora image. You can also use images of your own as the basis for a new image, for example if you have a base Apache image you could use this as the base of all your web application images. - -NOTE: By default, Docker obtains these base images from Docker Hub. - -Docker images are then built from these base images using a simple, descriptive set of steps we call instructions. Each instruction creates a new layer in our image. Instructions include actions like: - -. Run a command -. Add a file or directory -. Create an environment variable -. Run a process when launching a container - -These instructions are stored in a file called a Dockerfile. Docker reads this Dockerfile when you request a build of an image, executes the instructions, and returns a final image. - -**How does a Container work?** - -A container consists of an operating system, user-added files, and meta-data. As we've seen, each container is built from an image. That image tells Docker what the container holds, what process to run when the container is launched, and a variety of other configuration data. The Docker image is read-only. When Docker runs a container from an image, it adds a read-write layer on top of the image (using a union file system as we saw earlier) in which your application can then run. - -### Docker Machine - -Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them. - -Once your Docker host has been created, it then has a number of commands for managing containers: - -. Start, stop, restart container -. Upgrade Docker -. Configure the Docker client to talk to a host - -You used Docker Machine already during the attendee setup. We won't need it too much further on. But if you need to create hosts, it's a very handy tool to know about. From now on we're mostly going to use the docker client. - -Find out more about the details at the link:https://docs.docker.com/machine/[Docker Machine Website]. - -Check if docker machine is working: - - docker-machine -v - -It shows the output similar to the one shown below: - - docker-machine version 0.3.0 (0a251fe) - -NOTE: The exact version may differ based upon how recently the installation was performed. - -### Docker Client - -The client communicates with the demon process on your host and let's you work with images and containers. - -Check if your client is working using the following command: - - docker -v - -It shows the output similar to the following: - - Docker version 1.7.0, build 0baf609 - -NOTE: The exact version may differ based upon how recently the installation was performed. - -The most important options you'll be using frequently are: - -. `run` - runs a container -. `ps`- lists containers -. `stop` - stops a container -. `rm` - Removes a container - -Get a full list of available commands with - - docker - -A more comprehensive list of commands is also available in <>. - -### Verify Docker Configuration - -Check if your Docker Host is running: - - docker-machine ls - -You should see the output similar to: - -[source, text] ----- -NAME ACTIVE DRIVER STATE URL SWARM -lab virtualbox Running tcp://192.168.99.101:2376 ----- - -This machine is shown in "`Running`" state. If the machine state is stopped, start it with: - - docker-machine start lab - -After it is started you can find out IP address of your Docker Host with: - - docker-machine ip lab - -We already did this during the setup document, remember? So, this is a good chance to check, if you already added this IP to your hosts file. - -Type: - - ping dockerhost - -and see if this resolves to the IP address that the docker-machine command printed out. You should see an output as: - -[source, text] ----- -> ping dockerhost -PING dockerhost (192.168.99.101): 56 data bytes -64 bytes from 192.168.99.101: icmp_seq=0 ttl=64 time=0.394 ms -64 bytes from 192.168.99.101: icmp_seq=1 ttl=64 time=0.387 ms ----- - -If it does, you're ready to start with the lab. diff --git a/chapters/docker-commands.adoc b/chapters/docker-commands.adoc deleted file mode 100644 index 4a8ade3..0000000 --- a/chapters/docker-commands.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[Common_Docker_Commands]] -## Common Docker Commands - -Here is the list of commonly used Docker commands: - -[width="100%", options="header"] -|================== -| Purpose| Command -2+^s| Image -| Build an image| `docker build --rm=true .` -| Install an image | `docker pull ${IMAGE}` -| List of installed images | `docker images` -| List of installed images (detailed listing) | `docker images --no-trunc` -| Remove an image | `docker rmi ${IMAGE_ID}` -| Remove all untagged images | `docker rmi $(docker images \| grep “^” \| awk “{print $3}”)` -| Remove all images | `docker rm $(docker ps -aq)` -| Remove dangling images | `docker rmi $(docker images --quiet --filter "dangling=true")` -2+^s| Containers -| Run a container | `docker run` -| List of running containers | `docker ps` -| List of all containers | `docker ps -a` -| Stop a container | `docker stop ${CID}` -| Stop all running containers | `docker stop ``docker ps -q``` -| List all exited containers | `docker ps -a --filter "exited=1"` -| Remove a container | `docker rm ${CID}` -| Remove container by a regular expression | `docker ps -a \| grep wildfly \| awk '{print $1}' \| xargs docker rm -f` -| Remove all containers | `docker rm $(docker ps -aq)` -| Find IP address of the container | `docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID}` -| Attach to a container | `docker attach ${CID}` -| Open a shell in to a container | `docker exec -it ${CID} bash` -| Get container id for an image by a regular expression | `docker ps \| grep wildfly \| awk '{print $1}'` -|================== diff --git a/chapters/docker-compose.adoc b/chapters/docker-compose.adoc deleted file mode 100644 index 25531d4..0000000 --- a/chapters/docker-compose.adoc +++ /dev/null @@ -1,158 +0,0 @@ -[[Docker_Compose]] -## Multiple Containers Using Docker Compose - -[quote, github.com/docker/compose] -Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running. - -An application using Docker containers will typically consist of multiple containers. With Docker Compose, there is no need to write shell scripts to start your containers. All the containers are defined in a configuration file using _services_, and then `docker-compose` script is used to start, stop, and restart the application and all the services in that application, and all the containers within that service. The complete list of commands is: - -[options="header"] -|==== -| Command | Purpose -| `build` | Build or rebuild services -| `help` | Get help on a command -| `kill` | Kill containers -| `logs` | View output from containers -| `port` | Print the public port for a port binding -| `ps` | List containers -| `pull` | Pulls service images -| `restart` | Restart services -| `rm` | Remove stopped containers -| `run` | Run a one-off command -| `scale` | Set number of containers for a service -| `start` | Start services -| `stop` | Stop services -| `up` | Create and start containers -| `migrate-to-labels Recreate containers to add labels -|==== - -Docker Compose script is only available for OSX and Linux. https://github.com/arun-gupta/docker-java/issues/3 is used for tracking Docker Compose on Windows. - -### Configuration File - -. Entry point to Compose is `docker-compose.yml`. Lets use the following file: -+ -[source, yml] ----- -mysqldb: - image: mysql - environment: - MYSQL_DATABASE: sample - MYSQL_USER: mysql - MYSQL_PASSWORD: mysql - MYSQL_ROOT_PASSWORD: supersecret -mywildfly: - image: arungupta/wildfly-mysql-javaee7 - links: - - mysqldb:db - ports: - - 8080:8080 ----- -+ -This file is available in https://github.com/javaee-samples/docker-java/raw/master/attendees/docker-compose.yml[] and shows: -+ -.. Two services defined by the name `mysqldb` and `mywildfly` -.. Image name for each service defined using `image` -.. Environment variables for the MySQL container are defined in `environment` -.. MySQL container is linked with WildFly container using `links` -.. Port forwarding is achieved using `ports` - -### Start Services - -. All services can be started, in detached mode, by giving the command: -+ - docker-compose up -d -+ -And this shows the output as: -+ - Creating attendees_mysqldb_1... - Creating attendees_mywildfly_1... -+ -An alternate compose file name can be specified using `-f`. -+ -An alternate directory where the compose file exists can be specified using `-p`. -+ -. Started services can be verified as: -+ -[source, text] ----- -> docker-compose ps - Name Command State Ports -------------------------------------------------------------------------------------------------- -attendees_mysqldb_1 /entrypoint.sh mysqld Up 3306/tcp -attendees_mywildfly_1 /opt/jboss/wildfly/customi ... Up 0.0.0.0:8080->8080/tcp, 9990/tcp ----- -+ -This provides a consolidated view of all the services started, and containers within them. -+ -Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual `docker ps` command: -+ -[source, text] ----- -> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -3598e545bd2f arungupta/wildfly-mysql-javaee7:latest "/opt/jboss/wildfly/ 59 seconds ago Up 58 seconds 0.0.0.0:8080->8080/tcp, 9990/tcp attendees_mywildfly_1 -b8cf6a3d518b mysql:latest "/entrypoint.sh mysq 2 minutes ago Up 2 minutes 3306/tcp attendees_mysqldb_1 ----- -+ -. Service logs can be seen as: -+ -[source, text] ----- -> docker-compose logs -Attaching to attendees_mywildfly_1, attendees_mysqldb_1 -mywildfly_1 | => Starting WildFly server -mywildfly_1 | => Waiting for the server to boot -mywildfly_1 | ========================================================================= -mywildfly_1 | -mywildfly_1 | JBoss Bootstrap Environment -mywildfly_1 | -mywildfly_1 | JBOSS_HOME: /opt/jboss/wildfly -mywildfly_1 | -mywildfly_1 | JAVA: /usr/lib/jvm/java/bin/java -mywildfly_1 | -mywildfly_1 | JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -mywildfly_1 | - -. . . - -mywildfly_1 | 15:40:20,866 INFO [org.jboss.resteasy.spi.ResteasyDeployment] (MSC service thread 1-2) Deploying javax.ws.rs.core.Application: class org.javaee7.samples.employees.MyApplication -mywildfly_1 | 15:40:20,914 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017534: Registered web context: /employees -mywildfly_1 | 15:40:21,032 INFO [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "employees.war" (runtime-name : "employees.war") -mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management -mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990 -mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 9572ms - Started 280 of 334 services (92 services are lazy, passive or on-demand) -mysqldb_1 | Running mysql_install_db -mysqldb_1 | 2015-06-05 15:38:31 0 [Note] /usr/sbin/mysqld (mysqld 5.6.25) starting as process 27 ... -mysqldb_1 | 2015-06-05 15:38:31 27 [Note] InnoDB: Using atomics to ref count buffer pool pages - -. . . - -mysqldb_1 | 2015-06-05 15:38:40 1 [Note] Event Scheduler: Loaded 0 events -mysqldb_1 | 2015-06-05 15:38:40 1 [Note] mysqld: ready for connections. -mysqldb_1 | Version: '5.6.25' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) -mysqldb_1 | 2015-06-05 15:40:18 1 [Warning] IP address '172.17.0.24' could not be resolved: Name or service not known ----- - -### Verify Application - -. Access the application at http://dockerhost:8080/employees/resources/employees/. This is shown in the browser as: - -.Output From Servers Run Using Docker Compose -image::docker-compose-output.png[] - -### Stop Services - -. Stop the services as: -+ -[source, text] ----- -> docker-compose stop -Stopping attendees_mywildfly_1... -Stopping attendees_mysqldb_1... ----- - -### Scale Services - -https://github.com/arun-gupta/docker-java/issues/51 - diff --git a/chapters/docker-container-linking.adoc b/chapters/docker-container-linking.adoc deleted file mode 100644 index f918d5c..0000000 --- a/chapters/docker-container-linking.adoc +++ /dev/null @@ -1,45 +0,0 @@ -[[JavaEE7_Container_Linking]] -## Deploy Java EE 7 Application (Container Linking) - -<> explained how to use an in-memory database with the application server. This gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost when the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server. - -.Two Containers On Same Docker Host -image::javaee7-hol-container-linking.png[] - -This section will show how https://docs.docker.com/userguide/dockerlinks/[Docker Container Linking] can be used to connect to a service running inside a Docker container via a network port. - -. Start MySQL server as: -+ -[source, text] ----- -docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql ----- -+ -`-e` define environment variables that are read by the database at startup and allow us to access the database with this user and password. -+ -. Start WildFly and deploy Java EE 7 application as: -+ -[source, text] ----- -docker run -it --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7 ----- -+ -`--link` takes two parameters - first is name of the container we're linking to and second is the alias for the link name. -+ -.Container Linking -[NOTE] -=============================== -Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container. - -In our case, target container (WildFly) can see information about source container (MySQL). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. For example, IP address of MySQL server is expoed at $DB_PORT_3306_TCP_ADDR and port of MySQL server is exposed at $DB_PORT_3306_TCP_PORT. These are then used to create the JDBC resource. - -See more about container communication on the Docker website https://docs.docker.com/userguide/dockerlinks/[Linking Containers Together] -=============================== -+ -. See the output as: -+ -[source, text] ----- -> curl http://dockerhost:8080/employees/resources/employees -1Penny2Sheldon3Amy4Leonard5Bernadette6Raj7Howard8Priya ----- diff --git a/chapters/docker-container.adoc b/chapters/docker-container.adoc deleted file mode 100644 index d69d8db..0000000 --- a/chapters/docker-container.adoc +++ /dev/null @@ -1,344 +0,0 @@ -## Run Container - -The first step in running any application on Docker is to run a container from an image. There are plenty of images available from the official Docker registry (aka https://hub.docker.com[Docker Hub]). To run any of them, you just have to ask the Docker Client to run it. The client will check if the image already exists on Docker Host. If it exists then it'll run it, otherwise the host will download the image and then run it. - -### Pull Image - -Let's first check, if any images are available: - -[source, text] ----- -docker images ----- - -At first, this list is empty. Now, let's get a vanilla `jboss/wildfly` image: - -[source, text] ----- -docker pull jboss/wildfly ----- - -By default, docker images are retrieved from https://hub.docker.com/[Docker Hub]. - -You can see, that Docker is downloading the image with it's different layers. - -[NOTE] -==== -In a traditional Linux boot, the Kernel first mounts the root File System as read-only, checks its integrity, and then switches the whole rootfs volume to read-write mode. -When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. Consider each one of these file systems as a layer. - -At first, the top read-write layer has nothing in it, but any time a process creates a file, this happens in the top layer. And if something needs to update an existing file in a lower layer, then the file gets copied to the upper layer and changes go into the copy. The version of the file on the lower layer cannot be seen by the applications anymore, but it is there, unchanged. - -We call the union of the read-write layer and all the read-only layers a _union file system_. - -.Docker Layers -image::plain-wildfly0.png[] -==== - -In our particular case, the https://github.com/jboss-dockerfiles/wildfly/blob/master/Dockerfile[jboss/wildfly] image extends the https://github.com/jboss-dockerfiles/base/blob/master/Dockerfile[jboss/base-jdk:7] image which adds the OpenJDK distribution on top of the https://github.com/jboss-dockerfiles/base/blob/master/Dockerfile[jboss/base] image. -The base image is used for all JBoss community images. It provides a base layer that includes: - -. A jboss user (uid/gid 1000) with home directory set to `/opt/jboss` -. A few tools that may be useful when extending the image or installing software, like unzip. - -The "`jboss/base-jdk:7`" image adds: - -. OpenJDK 7 distribution -. Adds a `JAVA_HOME` environment variable - -When the download is done, you can list the images again and will see the following: - -[source, text] ----- -docker images -REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE -jboss/wildfly latest e908c8c95a8b 5 days ago 581.5 MB ----- - -### Run Container - -#### Interactive Container - -Run WildFly container in an interactive mode. - -[source, text] ----- -docker run -it jboss/wildfly ----- - -This will show the output as: - -[source, text] ----- -========================================================================= - - JBoss Bootstrap Environment - - JBOSS_HOME: /opt/jboss/wildfly - - JAVA: /usr/lib/jvm/java/bin/java - - JAVA_OPTS: -server -XX:+UseCompressedOops -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true - -========================================================================= - -OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0 -00:44:43,895 INFO [org.jboss.modules] (main) JBoss Modules version 1.4.3.Final -00:44:44,184 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.6.Final -00:44:44,267 INFO [org.jboss.as] (MSC service thread 1-2) WFLYSRV0049: WildFly Full 9.0.0.Final (WildFly Core 1.0.0.Final) starting - -. . . - -00:46:54,241 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management -00:46:54,243 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990 -00:46:54,250 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 9.0.0.Final (WildFly Core 1.0.0.Final) started in 4256ms - Started 203 of 379 services (210 services are lazy, passive or on-demand) ----- - -This shows that the server started correctly, congratulations! - -By default, Docker runs in the foreground. `-i` allows to interact with the STDIN and `-t` attach a TTY to the process. Switches can be combined together and used as `-it`. - -Hit Ctrl+C to stop the container. - -#### Detached Container - -Restart the container in detached mode: - -[source, text] ----- -docker run -d jboss/wildfly -972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a ----- - -`-d`, instead of `-it`, runs the container in detached mode. - -The output is the unique id assigned to the container. Check the logs as: - -[source, text] ----- -> docker logs 972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a -========================================================================= - - JBoss Bootstrap Environment - - JBOSS_HOME: /opt/jboss/wildfly - -. . . ----- - -We can check it by issuing the `docker ps` command which retrieves the images process which are running and the ports engaged by the process: - -[source, text] ----- -> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -922abbb9c63a jboss/wildfly "/opt/jboss/wildfly/ 3 seconds ago Up 2 seconds 8080/tcp desperate_lovelace ----- - -Also try `docker ps -a` to see all the containers on this machine. - -### Run Container with Default Port - -Startup log of the server shows that the server is located in the `/opt/jboss/wildfly`. It also shows that the public interfaces are bound to the `0.0.0.0` address while the admin interfaces are bound just to `localhost`. This information will be useful to learn how to customize the server. - -`docker-machine ip ` gives us the Docker Host IP address and this was already added to the hosts file. So, we can give it another try by accessing: http://dockerhost:8080. However, this will not work either. - -If you want containers to accept incoming connections, you will need to provide special options when invoking `docker run`. The container, we just started, can't be accessed by our browser. We need to stop it again and restart with different options. - -[source, text] ----- -docker stop `docker ps | grep wildfly | awk '{print $1}'` ----- - -Restart the container as: - -[source, text] ----- -docker run -d -P jboss/wildfly ----- - -`-P` map any exposed ports inside the image to a random port on Docker host. This can be verified as: - -[source, text] ----- -> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -63a69bff9c69 jboss/wildfly "/opt/jboss/wildfly/ 14 seconds ago Up 13 seconds 0.0.0.0:32768->8080/tcp kickass_bohr ----- - -The port mapping is shown in the `PORTS` column. Access the WildFly server at http://dockerhost:32768. Make sure to use the correct port number as shown in your case. - -NOTE: Exact port number may be different in your case. - -### Run Container with Specified Port - -Lets stop the previously running container as: - -[source, text] ----- -docker stop `docker ps | grep wildfly | awk '{print $1}'` ----- - -Restart the container as: - -[source, text] ----- -docker run -it -p 8080:8080 jboss/wildfly ----- - -The format is `-p hostPort:containerPort`. This option maps container ports to host ports and allows other containers on our host to access them. - -.Docker Port Mapping -[NOTE] -=============================== -Port exposure and mapping are the keys to successful work with Docker. -See more about networking on the Docker website link:https://docs.docker.com/articles/networking/[Advanced Networking] -=============================== - -Now we're ready to test http://dockerhost:8080 again. This works with the exposed port, as expected. - -.Welcome WildFly -image::plain-wildfly1.png[] - -[[Enabling_WildFly_Administration]] -### Enabling WildFly Administration - -Default WildFly image exposes only port 8080 and thus is not available for administration using either the CLI or Admin Console. Lets expose the ports in different ways. - -#### Default Port Mapping - -The following command will override the default command in Docker file, start WildFly, and bind application and management port to all network interfaces. - -[source, text] ----- -docker run -P -d jboss/wildfly /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 ----- - -Accessing WildFly Administration Console require a user in administration realm. A pre-created image, with appropriate username/password credentials, is used to start WildFly as: - -[source, text] ----- -docker run -P -d arungupta/wildfly-management ----- - -`-P` map any exposed ports inside the image to a random port on Docker host. - -Look at the exposed ports as: - -[source, text] ----- -docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -af7d6914a1f9 arungupta/wildfly-management "/opt/jboss/wildfly/ 2 seconds ago Up 1 seconds 0.0.0.0:32770->8080/tcp, 0.0.0.0:32769->9990/tcp happy_bardeen ----- - -Look for the host port that is mapped in the container, `32769` in this case. Access the admin console at http://dockerhost:32769. - -NOTE: Exact port number may be different in your case. - -The username/password credentials are: - -[[WildFly_Administration_Credentials]] -[options="header"] -|==== -| Field | Value -| Username | admin -| Password | docker#admin -|==== - -This shows the admin console as: - -.Welcome WildFly -image::wildfly-admin-console.png[] - -##### Additional Ways To Find Port Mapping - -The exact mapped port can also be found as: - -. Using `docker port`: -+ -[source, text] ----- -docker port 6f610b310a46 ----- -+ -to see the output as: -+ -[source, text] ----- -0.0.0.0:32769->8080/tcp -0.0.0.0:32770->9990/tcp ----- -+ -. Using `docker inspect`: -+ -[source, text] ----- -docker inspect --format='{{(index (index .NetworkSettings.Ports "9990/tcp") 0).HostPort}}' ----- - -[[Management_Fixed_Port_Mapping]] -#### Fixed Port Mapping - -This management image can also be started with a pre-defined port mapping as: - -[source, text] ----- -docker run -p 8080:8080 -p 9990:9990 -d arungupta/wildfly-management ----- - -In this case, Docker port mapping will be shown as: - -[source, text] ----- -8080/tcp -> 0.0.0.0:8080 -9990/tcp -> 0.0.0.0:9990 ----- - -### Stop and Remove Container - -#### Stop Container - -. Stop a specific container: -+ -[source, text] ----- -docker stop ----- -+ -. Stop all the running containers -+ -[source, text] ----- -docker rm $(docker stop $(docker ps -q)) ----- -+ -. Stop only the exited containers -+ -[source, text] ----- -docker ps -a -f "exited=-1" ----- - -#### Remove Container - -. Remove a specific container: -+ -[source, text] ----- -docker rm 0bc123a8ece0 ----- -+ -. Containers meeting a regular expression -+ -[source, text] ----- -docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm ----- -+ -. All running containers, without any criteria -+ -[source, text] ----- -docker rm $(docker ps -aq) ----- diff --git a/chapters/docker-continuous-delivery.adoc b/chapters/docker-continuous-delivery.adoc deleted file mode 100644 index 722aab4..0000000 --- a/chapters/docker-continuous-delivery.adoc +++ /dev/null @@ -1,4 +0,0 @@ -## Continuous Delivery Using Docker - -https://github.com/jbossdemocentral/continuous-delivery-demo -https://github.com/amorena/democdonpaas \ No newline at end of file diff --git a/chapters/docker-deployment-options.adoc b/chapters/docker-deployment-options.adoc deleted file mode 100644 index 83a1192..0000000 --- a/chapters/docker-deployment-options.adoc +++ /dev/null @@ -1,219 +0,0 @@ -## Build and Deploy Java EE 7 Application - -https://github.com/javaee-samples/javaee7-simple-sample[Java EE 7 Simple Sample] is a trivial Java EE 7 sample application. - -[[Build_Application]] -### Build Application - -. Clone the repo: - - git clone https://github.com/javaee-samples/javaee7-simple-sample.git - -. Build the application: - - mvn clean package - -### Start Application Server - -Start WildFly server as: - -[source, text] ----- -docker run --name wildfly -d -p 8080:8080 -v /Users/youruser/tmp/deployments:/opt/jboss/wildfly/standalone/deployments/:rw jboss/wildfly ----- - -Make sure to replace `/Users/youruser/tmp/deployments` to a directory on your local machine. Also, make sure this directory already exists. For example, on my machine this directory is `/Users/arungupta/tmp/deployments`. - -This command starts a container named "`wildfly`". - -The `-v` flag maps a directory from the host into the container. This will be the directory to put the deployments. `rw` ensures that the Docker container can write to it. - -WARNING: Windows users, please make sure to use `-v /c/Users/` notation for drive letters. - -Check logs to verify if the server has started. - -[source, text] ----- -docker logs -f wildfly ----- - -Access http://dockerhost:8080 in your browser to make sure the instance is up and running. - -Now you're ready to deploy the application for the first time. - -### Configure JBoss Developer Studio - -Start JBoss Developer Studio, if not already started. - -. Select '`Servers`' tab, create a new server adapter -+ -.Server adapter -image::jbds1.png[] -+ -. Assign an existing or create a new WildFly 9.0.0 runtime (changed properties are highlighted.) -+ -.WildFly Runtime Properties -image::jbds2.png[] -+ -. If a new runtime needs to be created, pick the directory for WildFly 9.0.0: -+ -.WildFly 9.0.0.Final Runtime -image::jbds3.png[] -+ -Click on '`Finish`'. -+ -. Double-click on the newly selected server to configure server properties: -+ -.Server properties -image::jbds4.png[] -+ -The host name is specified to '`dockerhost`'. Two properties on the left are automatically propagated from the previous dialog. Additional two properties on the right side are required to disable to keep deployment scanners in sync with the server. -+ -. Specify a custom deployment folder on Deployment tab of Server Editor -+ -.Custom deployment folder -image::jbds5.png[] -+ -. Right-click on the newly created server adapter and click '`Start`'. -+ -.Started server -image::jbds6.png[] - -### Deploy Application Using Shared Volumes - -. Import javaee7-simple-sample application source code using Import -> Existing Maven Projects. -. Right-click on the project, select '`Run on Server`' and chose the previously created server. - -The project runs and displays the start page of the application. - -.Start Server -image::jbds7.png[] - -Congratulations! - -You've deployed your first application to WildFly running in a Docker container from JBoss Developer Studio. - -Stop WildFly container when you're done. - - docker stop wildfly - -### Deploy Application Using CLI - -The Command Line Interface (CLI) is a tool for connecting to WildFly instances to manage all tasks from command line environment. Some of the tasks that you can do using the CLI are: - -. Deploy/Undeploy web application in standalone/Domain Mode. -. View all information about the deployed application on runtime. -. Start/Stop/Restart Nodes in respective mode i.e. Standalone/Domain. -. Adding/Deleting resource or subsystems to servers. - -Lets use the CLI to deploy javaee7-simple-sample to WildFly running in the container. - -. CLI needs to be locally installed and comes as part of WildFly. This should be available in the previously downloaded WildFly. Unzip into a folder of your choice (e.g. `/Users/arungupta/tools/`). This will create `wildfly-9.0.0.Final` directory here. This folder is referred to $WIDLFY_HOME from here on. Make sure to add the `/Users/arungupta/tools/wildfly-9.0.0.Final/bin` to your $PATH. -+ -. Run the "`wildfly-management`" image with fixed port mapping as explained in <>. -. Run the `jboss-cli` command and connect to the WildFly instance. -+ -[source, text] ----- -jboss-cli.sh --controller=dockerhost:9990 -u=admin -p=docker#admin -c ----- -+ -This will show the output as: -+ -[source, text] ----- -[standalone@dockerhost:9990 /] ----- -+ -. Deploy the application as: -+ -[source, text] ----- -deploy target/javaee7-simple-sample-1.10.war --force ----- - -Now you've sucessfully used the CLI to remote deploy the Java EE 7 sample application to WildFly running as docker container. - -### Deploy Application Using Web Console - -WildFly comes with a web-based administration console. It also relies on the same management APIs that are used by JBoss Developer Tools and the CLI. It provides a simple and easy to use web-based console to manage WildFly instance. For a Docker image, it needs to be explicitly enabled as explained in <>. Once enabled, it can be accessed at http://dockerhost:9990. - -.WildFly Web Console -image::console1.png[] - -Username and password credentials are shown in <>. - -[NOTE] -==== -You may like to stop and remove the Docker container running WildFly. This can be done as `docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f`. - -Start a new container as `docker run -d --name wildfly -p 8080:8080 -p 9990:9990 arungupta/wildfly-management`. -==== - -Deploy the application using the console with the following steps: - -. Go to '`Deployments`' tab. -+ -.Deployments tab in WildFly Web Console -image::wildfly9-deployments-tab.png[] -+ -. Click on '`Add`' button. -. On '`Add Deployment`' screen, take the default of '`Upload a new deployment`' and click '`Next>>`'. -. Click on '`Choose File`', select `/javaee7-simple-sample.war` file on your computer. This would be `javaee7-simple-sample/target/javaee7-simple-sample.war` from <>. -. Click on '`Next>>`'. -. Select '`Enable`' checkbox. -+ -.Enable a deployment -image::wildfly9-add-deployments.png[] -+ -. Click '`Finish`'. -+ -.Java EE 7 Simple Sample Deployed -image::wildfly9-javaee7-simple-sample-deployed.png[] - -This will complete the deployment of the Java EE 7 application using Web Console. The output can be seen out http://dockerhost:8080/javaee7-simple-sample and looks like: - -.Java EE 7 Simple Sample Output -image::wildfly9-javaee7-simple-sample-output.png[] - -### Deploy Application Using Management API - -A standalone WildFly process, process can be configured to listen for remote management requests using its "`native management interface`". The CLI tool that comes with the application server uses this interface, and user can develop custom clients that use it as well. By default, WildFly management interface listens on 127.0.0.1. When running inside a Docker container, the network interface should be bound to all publicly assigned addresses. This can be easily changed by biding to 0.0.0.0 instead of 127.0.0.1. - -. Start another WildFly instance again: -+ -[source, text] ----- -docker run -d --name wildfly -p 8080:8080 -p 9990:9990 arungupta/wildfly-management ----- -+ -In addition to application port 8080, the administration port 9990 is exposed as well. The WildFly image that is used has tweaked the start script such that the management interface is bound to 0.0.0.0. -+ -. Create a new server adapter in JBoss Developer Studio and name it "`WildFly 9.0.0-Management`". Specify the host name as '`dockerhost`'. -+ -image::jbds8.png[] -+ -. Click on '`Next>`' and change the values as shown. -+ -.Create New Server Adapter -image::jbds9.png[] -+ -. Take the default values in '`Remote System Integration`' and click on '`Finish`'. -+ -. Change server properties by double clicking on the newly created server adapter. Specify admin credentials (username: docker, password: docker#admin). Note, you need to delete the existing password and use this instead: -+ -.Management Login Credentials -image::jbds10.png[] -+ -. Right-click on the newly created server adapter and click '`Start`'. Status quickly changes to '`Started`' as shown. -+ -.Synchronized WildFly Server -image::jbds11.png[] -+ -. Right-click on the javaee7-simple-sample project, select '`Run on Server`' and choose this server. The project runs and displays the start page of the application. -. Stop WildFly when you're done. -+ -[source, text] ----- -docker stop wildfly ----- diff --git a/chapters/docker-eclipse.adoc b/chapters/docker-eclipse.adoc deleted file mode 100644 index cacab24..0000000 --- a/chapters/docker-eclipse.adoc +++ /dev/null @@ -1,143 +0,0 @@ -## Docker Tools in Eclipse - -The Docker tooling is aimed at providing at minimum the same basic level features as the command-line interface, but also provide some advantages by having access to a full fledged UI. - -### Install Docker Tools Plugins - -As this is still in early access stage, you will have to install it first: - -. Use JBoss Developer Studio 9.0 Beta 2. -+ -Alternatively, download http://www.eclipse.org/downloads/index-developer-default.php[Eclipse Mars latest build] and configure JBoss Tools plugin from the update site http://download.jboss.org/jbosstools/updates/nightly/mars/. -+ -. Open JBoss Developer Studio 9.0 Nightly -. Add a new site using the menu items: '`Help`' > '`Install New Software...`' > '`Add...`'. -+ -Specify the '`Name:`' as "`Docker Nightly`" and '`Location:`' as http://download.eclipse.org/linuxtools/updates-docker-nightly/. -+ -.Add Docker Tooling To JBoss Developer Studio -image::jbds-docker-tools1.png[] -+ -. Expand Linux Tools, select '`Docker Client`' and '`Docker Tooling`'. -+ -.Add Docker Tooling -image::jbds-docker-tools-nightly-setup.png[] -+ -. Click on '`Next >`', '`Next >`', accept the terms of the license agreement, and click on '`Finish`'. This will complete the installation of plugins. -+ -Restart the IDE for the changes to take effect. - -### Docker Explorer - -The Docker Explorer provides a wizard to establish a new connection to a Docker daemon. This wizard can detect default settings if the user’s machine runs Docker natively (such as in Linux) or in a VM using Boot2Docker (such as in Mac or Windows). Both Unix sockets on Linux machines and the REST API on other OSes are detected and supported. The wizard also allows remote connections using custom settings. - -. Use the menu '`Window`', '`Show View`', '`Other...`'. Type '`docker`' to see the output as: -+ -image::jbds-docker-tools-docker-view.png[] -+ -. Select '`Docker Explorer`' to open Docker Explorer. -+ -image::jbds-docker-tools-docker-explorer-view.png[] -+ -. Click on the link in this window to create a connection to Docker Host. Specify the settings as shown: -+ -.Docker Explorer -image::jbds-docker-tools2.png[] -+ -Make sure to get IP address of the Docker Host as: -+ -[source, text] ----- -docker-machine ip lab ----- -+ -Also, make sure to specify the correct directory for `.docker` on your machine. -+ -. Click on '`Test Connection`' to check the connection. This should show the output as: -+ -.Docker Explorer -image::jbds-docker-tools-test-connection-output.png[] -+ -Click on '`OK`' and '`Finish`' to exit out of the wizard. -+ -. Docker Explorer itself is a tree view that handles multiple connections and provides users with quick overview of the existing images and containers. -+ -.Docker Explorer Tree View -image::jbds-docker-tools3.png[] -+ -. Customize the view by clicking on the arrow in toolbar: -+ -.Docker Explorer Customize View -image::jbds-docker-tools-customize-view-option.png[] -+ -Built-in filters can show/hide intermediate and '`dangling`' images, as well as stopped containers. -+ -.Docker Explorer Customize View Wizard -image::jbds-docker-tools-customize-view-wizard.png[] - -### Docker Images - -The Docker Images view lists all images in the Docker host selected in the Docker Explorer view. This view allows user to manage images, including: - -. Pull/push images from/to the Docker Hub Registry (other registries will be supported as well, https://bugs.eclipse.org/bugs/show_bug.cgi?id=469306[#469306]) -. Build images from a Dockerfile -. Create a container from an image - -Lets take a look at it. - -. Use the menu '`Window`', '`Show View`', '`Other...`', select '`Docker Images`'. It shows the list of images on Docker Host: -+ -.Docker Images View -image::jbds-docker-tools4.png[] -+ -. Right-click on the image ending with "`wildfly:latest`" and click on the green arrow in the toolbar. This will show the following wizard: -+ -.Docker Run Container Wizard -image::jbds-docker-tools-run-container-wizard.png[] -+ -By default, all exports ports from the image are mapped to random ports on the host interface. This setting can be changed by unselecting the first checkbox and specify exact port mapping. -+ -Click on '`Finish`' to start the container. -+ -. When the container is started, all logs are streamed into Eclipse Console: -+ -.Docker Container Logs -image::jbds-docker-tools5.png[] - -### Docker Containers - -Docker Containers view lets the user manage the containers. The view toolbar provides commands to start, stop, pause, unpause, display the logs and kill containers. - -. Use the menu '`Window`', '`Show View`', '`Other...`', select '`Docker Containers`'. It shows the list of running containers on Docker Host: -+ -.Docker Containers View -image::jbds-docker-tools6.png[] -+ -. Pause the container by clicking on the "`pause`" button in the toolbar (https://bugs.eclipse.org/bugs/show_bug.cgi?id=469310[#469310]). Show the complete list of containers by clicking on the '`View Menu`', '`Show all containers`'. -+ -.All Docker Containers -image::jbds-docker-tools-all-containers.png[] -+ -. Select the paused container, and click on the green arrow in the toolbar to restart the container. -. Right-click on any running container and select "`Display Log`" to view the log for this container. -+ -.Eclipse Properties View -image::jbds-docker-tools-display-log.png[] - -TODO: Users can also attach an Eclipse console to a running Docker container to follow the logs and use the STDIN to interact with it. - -### Details on Images and Containers - -Eclipse Properties view is used to provide more information about the containers and images. - -. Just open the Properties View and click on a Connection, Container, or Image in any of the Docker Explorer View, Docker Containers View, or Docker Images View. This will fill in data in the Properties view. -+ -Info view is shown as: -+ -.Docker Container Properties View Info -image::jbds-docker-tools-properties-info.png[] -+ -Inspect view is shown as: -+ -.Docker Container Properties View Inspect -image::jbds-docker-tools-properties-inspect.png[] diff --git a/chapters/docker-intellij.adoc b/chapters/docker-intellij.adoc deleted file mode 100644 index 865b465..0000000 --- a/chapters/docker-intellij.adoc +++ /dev/null @@ -1,3 +0,0 @@ -## Docker Tools in IntelliJ - -http://blog.jetbrains.com/idea/2015/03/docker-support-in-intellij-idea-14-1/ \ No newline at end of file diff --git a/chapters/docker-javaee7.adoc b/chapters/docker-javaee7.adoc deleted file mode 100644 index 03d2c5a..0000000 --- a/chapters/docker-javaee7.adoc +++ /dev/null @@ -1,49 +0,0 @@ -[[JavaEE7_PreBuilt_WAR]] -## Deploy Java EE 7 Application (Pre-Built WAR) - -https://github.com/javaee-samples/javaee7-hol[Java EE 7 Movieplex] is a standard multi-tier enterprise application that shows design patterns and anti-patterns for a typical Java EE 7 application. - -.Java EE 7 Application Architecture -image::javaee7-hol.png[] - -Pull the Docker image that contains WildFly and pre-built Java EE 7 application WAR file as shown: - -[source, text] ----- -docker pull arungupta/javaee7-hol ----- - -The https://github.com/arun-gupta/docker-images/blob/master/javaee7-hol/Dockerfile[javaee7-hol Dockerfile] is based on `jboss/wildfly` and adds the movieplex7 application as war file. - -Run it: - -[source, text] ----- -docker run -it -p 8080:8080 arungupta/javaee7-hol ----- - -See the application in action at http://dockerhost:8080/movieplex7/. The output is shown: - -.Java EE 7 Application Output -image::javaee7-movieplex7.png[] - -This uses an in-memory database with WildFly application server as shown in the image: - -.In-memory Database -image::javaee7-hol-in-memory-database.png[] - -Only two changes are required to the standard `jboss/wildfly` image: - -. By default, WildFly starts in Web platform. This Java EE 7 application uses some capabilities from the Full Platform and so WildFly is started in that mode instead as: -+ -[source, text] ----- -CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"] ----- -+ -. WAR file is copied to the `standalone/deployments` directory as: -+ -[source, text] ----- -RUN curl -L https://github.com/javaee-samples/javaee7-hol/raw/master/solution/movieplex7-1.0-SNAPSHOT.war -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war ----- diff --git a/chapters/docker-kubernetes-fabric8.adoc b/chapters/docker-kubernetes-fabric8.adoc deleted file mode 100644 index 00038e6..0000000 --- a/chapters/docker-kubernetes-fabric8.adoc +++ /dev/null @@ -1,26 +0,0 @@ -== Kubernetes and Fabric8 -Fabric8 is a set of tools and services geared toward middleware and application developers that make it easy to develop microervices using Docker and Kubernetes. - -=== Fabic 8 Console - -The Fabric8 console is rich with visual diagrams showing what you've got deployed, where it's deployed, how many, and so on. You can also make changes to your kubernetes cluster (deploy apps, edit replica sizes, delete services, etc) from a single dashboard. Screen shots and demos to come. - - -=== Inject k8s resources using @Inject in Java EE client -Fabric8 has lots of java [libraries](http://fabric8.io/guide/javaLibraries.html) for making working with kubernetes and kubernetes resources easier. For example, there is a [kubernetes Java client](https://github.com/fabric8io/kubernetes-client) with a fluent DSL for interacting with the Kube API. More examples to come. - -=== Maven plugin to generate JSON for your WAR file and deploy it in k8s -Java developers are used to Maven and other tools in the Java ecosystem. Fabric8's maven plugins aim to bridge the gap between app development and the kubernetes cluster engine. With these plugins you can create docker images and control how they're created using Maven properties and plugin configurations. You can also generate the kubenetes JSON files, inject environment variables, and also apply the JSON directly to Kube. - -=== Built in CI/CD with workflow and promotion -Java developers eventually want to deploy their application. Fabric8 brings a set of curated, yet pluggable, services like Git, Jenkins, Nexus, Gerrit and integrates them together with an issue tracker, chat room, and flexible per-project configurations which allow you to set up CI/CD with proper gates and promotion practices with a single click or with a single yml file. - -=== Out of the box tooling for your Apache Camel apps -Apache Camel is a very powerful integration library and can be used along with Fabric8 and Kubernetes to provide an iPaaS. The tooling included in Fabric8 gives a UI based access to visualizations, debugging, tracing, metrics and indicators, etc. - -=== API management for your APIs -Accessing your services can become complicated if you consider token provisioning, authZ/authN, metering, chargeback, etc,etc. Fabric8 has built in API management for your APIs. - -=== Logging/Metrics for your apps built in -Fabric8 leverages InfluxDB/Grafana and Elasticsearch/Kibana for in-container metrics and logging that is valuable for any insight into what your apps or middleware are doing - diff --git a/chapters/docker-kubernetes.adoc b/chapters/docker-kubernetes.adoc deleted file mode 100644 index e34172b..0000000 --- a/chapters/docker-kubernetes.adoc +++ /dev/null @@ -1,696 +0,0 @@ -## Java EE Application on Kubernetes Cluster - -[quote, github.com/GoogleCloudPlatform/kubernetes/] -Kubernetes is an open source system for managing containerized applications across multiple hosts, providing basic mechanisms for deployment, maintenance, and scaling of applications. - -Kubernetes, or "`k8s`" in short, allows the user to provide declarative primitives for the desired state, for example "`need 5 WildFly servers and 1 MySQL server running`". Kubernetes self-healing mechanisms, such as auto-restarting, re-scheduling, and replicating containers then ensure this state is met. The user just define the state and Kubernetes ensures that the state is met at all times on the cluster. - -*How is it related to Docker?* - -Docker provides the lifecycle management of containers. A Docker image defines a build time representation of the runtime containers. There are commands to start, stop, restart, link, and perform other lifecycle methods on these containers. Kubernetes uses Docker to package, instantiate, and run containerized applications. - -*How does Kubernetes simplify containerized application deployment?* - -A typical application would have a cluster of containers across multiple hosts. For example, your web tier (for example Undertow) might run as a few instances, and likely on a set of containers. Similarly, your application tier (for example, WildFly) would run on a different set of containers. The web tier would need to delegate the request to application tier. The web, application, and database tier would generally run on a separate set of containers. These containers would need to talk to each other. Using any of the solutions mentioned above would require scripting to start the containers, and monitoring/bouncing if something goes down. Kubernetes does all of that for the user after the application state has been defined. - -### Key Components - -At a very high level, there are three key components: - -. *Pods* are the smallest deployable units that can be created, scheduled, and managed. Its a logical collection of containers that belong to an application. -. *Master* is the central control point that provides a unified view of the cluster. There is a single master node that control multiple minions. -. *Node* is a worker node that run tasks as delegated by the master. Minions can run one or more pods. It provides an application-specific "`virtual host`" in a containerized environment. - -A picture is always worth a thousand words and so this is a high-level logical block diagram for Kubernetes: - -.Kubernetes Key Components -image::kubernetes-key-components.png[] - -After the 50,000 feet view, lets fly a little lower at 30,000 feet and take a look at how Kubernetes make all of this happen. There are a few key components at Master and Minion that make this happen. - -. *Replication Controller* is a resource at Master that ensures that requested number of pods are running on minions at all times. -. *Service* is an object on master that provides load balancing across a replicated group of pods. -Label is an arbitrary key/value pair in a distributed watchable storage that the Replication Controller uses for service discovery. -. *Kubelet* Each minion runs services to run containers and be managed from the master. In addition to Docker, Kubelet is another key service installed there. It reads container manifests as YAML files that describes a pod. Kubelet ensures that the containers defined in the pods are started and continue running. -. Master serves *RESTful Kubernetes API* that validate and configure Pod, Service, and Replication Controller. - -### Start Kubernetes Cluster - -Kubernetes cluster can be easily started using Vagrant. There are two options to start the cluster - first using a downloaded Kubernetes distribution bundle and second by downloading the latest bundle as part of the install. - -#### Using Previously Downloaded Kubernetes Distribution - -. Setup a Kubernetes cluster as: -+ -[source, text] ----- -cd kubernetes - -export KUBERNETES_PROVIDER=vagrant -./cluster/kube-up.sh ----- -+ -The `KUBERNETES_PROVIDER` environment variable tells all of the various cluster management scripts which variant to use. -+ -NOTE: This will take a few minutes, so be patience! Vagrant will provision each machine in the cluster with all the necessary components to run Kubernetes. -+ -It shows the output as: -+ -[source, text] ----- -Starting cluster using provider: vagrant -... calling verify-prereqs -... calling kube-up -Using credentials: vagrant:vagrant - -. . . - -Cluster validation succeeded -Done, listing cluster services: - -Kubernetes master is running at https://10.245.1.2 -KubeDNS is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-dns -KubeUI is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-ui ----- -+ -Note down the address for Kubernetes master, `https://10.245.1.2` in this case. - -#### Download and Start the Cluster Together - -. Alternatively, the cluster can also be started as: -+ -[source, text] ----- -> curl -sS https://get.k8s.io | bash -Downloading kubernetes release v0.21.1 to /Users/arungupta/tools/kubernetes.tar.gz ---2015-07-13 15:56:54-- https://storage.googleapis.com/kubernetes-release/release/v0.21.1/kubernetes.tar.gz -Resolving storage.googleapis.com... 74.125.28.128, 2607:f8b0:400e:c02::80 -Connecting to storage.googleapis.com|74.125.28.128|:443... connected. -HTTP request sent, awaiting response... 200 OK -Length: 117901998 (112M) [application/x-tar] -Saving to: 'kubernetes.tar.gz' - -kubernetes.tar.gz 100%[=========================================================>] 112.44M 6.21MB/s in 18s - -2015-07-13 15:57:13 (6.13 MB/s) - 'kubernetes.tar.gz' saved [117901998/117901998] - -. . . - -NAME STATUS MESSAGE ERROR -controller-manager Healthy ok nil -scheduler Healthy ok nil -etcd-0 Healthy {"health": "true"} nil -Cluster validation succeeded -Done, listing cluster services: - -Kubernetes master is running at https://10.245.1.2 -KubeDNS is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-dns -KubeUI is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-ui - -Kubernetes binaries at /Users/arungupta/tools/kubernetes/kubernetes/cluster/ -You may want to add this directory to your PATH in $HOME/.profile -Installation successful! ----- - -#### Verify the Cluster - -. Verify the Kubernetes cluster as: -+ -[source, text] ----- -kubernetes> vagrant status -Current machine states: - -master running (virtualbox) -minion-1 running (virtualbox) - -This environment represents multiple VMs. The VMs are all listed -above with their current state. For more information about a specific -VM, run `vagrant status NAME`. ----- -+ -By default, the Vagrant setup will create a single kubernetes-master and 1 kubernetes-minion. Each VM will take 1 GB, so make sure you have at least 2GB to 4GB of free memory (plus appropriate free disk space). -+ -NOTE: By default, only one minion is created. This can be manipulated by setting an environment variable NUM_MINIONS variable to an integer before invoking `kube-up.sh` script. -+ -.Kubernetes Cluster using Vagrant -image::kubernetes-cluster-vagrant.png[] -+ -By default, each VM in the cluster is running Fedora, Kubelet is installed into ``systemd'', and all other Kubernetes services are running as containers on Master. -+ -. Access https://10.245.1.2 (or whatever IP address is assigned to your kubernetes cluster start up log). This may present the warning as shown below: -+ -image::kubernetes-master-default-output-certificate.png[] -+ -Click on '`Advanced`' and then on '`Proceed to 10.245.1.2`' to see the output as: -+ -.Kubernetes Output from Master -image::kubernetes-master-default-output.png[] -+ -Use '`vagrant`' as the username and '`vagrant`' as the password. -+ -Check the list of nodes as: -+ -[source, text] ----- -> ./cluster/kubectl.sh get nodes -NAME LABELS STATUS -10.245.1.3 kubernetes.io/hostname=10.245.1.3 Ready ----- -+ -. Check the list of pods: -+ -[source, text] ----- -kubernetes> ./cluster/kubectl.sh get po -NAME READY STATUS RESTARTS AGE ----- -+ -. Check the list of services running: -+ -[source, text] ----- -kubernetes> ./cluster/kubectl.sh get se -NAME LABELS SELECTOR IP(S) PORT(S) -kubernetes component=apiserver,provider=kubernetes 10.247.0.1 443/TCP ----- -+ -. Check the list of replication controllers: -+ -[source, text] ----- -kubernetes> ./cluster/kubectl.sh get rc -CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS ----- - -### Deploy Java EE Application (multiple configuration files) - -Pods, and the IP addresses assigned to them, are ephemeral. If a pod dies then Kubernetes will recreate that pod because of its self-healing features, but it might recreate it on a different host. Even if it is on the same host, a different IP address could be assigned to it. And so any application cannot rely upon the IP address of the pod. - -Kubernetes services is an abstraction which defines a logical set of pods. A service is typically back-ended by one or more physical pods (associated using labels), and it has a permanent IP address that can be used by other pods/applications. For example, WildFly pod can not directly connect to a MySQL pod but can connect to MySQL service. In essence, Kubernetes service offers clients an IP and port pair which, when accessed, redirects to the appropriate backends. - -.Kubernetes Service -image::kubernetes-service.png[] - -NOTE: In this case, all the pods are running on a single minion. This is because, that is the default number for a Kubernetes cluster. The pod can very be on another minion if more number of minions are configured to start in the cluster. - -Any Service that a Pod wants to access must be created before the Pod itself, or else the environment variables will not be populated. - -The order of Service and the targeted Pods does not matter. However Service needs to be started before any other Pods consuming the Service are started. - -#### Start MySQL Pod - -. Start MySQL Pod: -+ -[source, text] ----- -./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-mysql-pod.yaml -pods/mysql-pod ----- -+ -It uses the following configuration file: -+ -[source, yaml] ----- -apiVersion: v1 -kind: Pod -metadata: - name: mysql-pod - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - containers: - - - name: mysql - image: mysql:latest - env: - - - name: "MYSQL_USER" - value: "mysql" - - - name: "MYSQL_PASSWORD" - value: "mysql" - - - name: "MYSQL_DATABASE" - value: "sample" - - - name: "MYSQL_ROOT_PASSWORD" - value: "supersecret" - ports: - - - containerPort: 3306 ----- -+ -. Get status of the Pod: -+ -[source, text] ----- -kubernetes> ./cluster/kubectl.sh get -w po -NAME READY STATUS RESTARTS AGE -mysql-pod 0/1 Pending 0 4s -NAME READY STATUS RESTARTS AGE -mysql-pod 0/1 Running 0 44s -mysql-pod 1/1 Running 0 44s ----- -+ -`-w` watches for changes to the requested object. Wait for the MySQL pod to be in Running status. - -#### Start MySQL service - -. Start MySQL Service: -+ -[source, text] ----- -./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-mysql-service.yaml -services/mysql-service ----- -+ -It uses the following configuration file: -+ -[source, yaml] ----- -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql-pod - context: docker-k8s-lab ----- -+ -Once again, the label "`context: docker-k8s-lab`" is used. This simplifies querying the created pods later on. -+ -. Get status of the Service: -+ -[source, text] ----- -./cluster/kubectl.sh get -w se -NAME LABELS SELECTOR IP(S) PORT(S) -kubernetes component=apiserver,provider=kubernetes 10.247.0.1 443/TCP -mysql-service context=docker-k8s-lab,name=mysql-pod context=docker-k8s-lab,name=mysql-pod 10.247.63.43 3306/TCP ----- -+ -If multiple services are running, then it can be narrowed by specifying the labels: -+ -[source, text] ----- -./cluster/kubectl.sh get -w po -l context=docker-k8s-lab,name=mysql-pod -NAME READY STATUS RESTARTS AGE -mysql-pod 1/1 Running 0 4m ----- -+ -This is also the selector label used by Service to target Pods. -+ -When a Service is run on a node, the kubelet adds a set of environment variables for each active Service. It supports both Docker links compatible variables and simpler `{SVCNAME}_SERVICE_HOST` and `{SVCNAME}_SERVICE_PORT` variables, where the Service name is upper-cased and dashes are converted to underscores. -+ -Our service name is "`mysql-service`" and so `MYSQL_SERVICE_SERVICE_HOST` and `MYSQL_SERVICE_SERVICE_PORT` variables are available to other pods. - -Kubernetes also allows services to be resolved using DNS configuration. Send a Pull Request for adding this functionality to the lab as explained in https://github.com/javaee-samples/docker-java/issues/62[#62]. - -#### Start WildFly Replication Controller - -. Start WildFly replication controller: -+ -[source, text] ----- -./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-wildfly-rc.yaml -replicationcontrollers/wildfly-rc ----- -+ -It uses the following configuration file: -+ -[source, yaml] ----- -apiVersion: v1 -kind: ReplicationController -metadata: - name: wildfly-rc - labels: - name: wildfly - context: docker-k8s-lab -spec: - replicas: 1 - template: - metadata: - labels: - name: wildfly - spec: - containers: - - name: wildfly-rc-pod - image: arungupta/wildfly-mysql-javaee7:k8s - ports: - - containerPort: 8080 ----- -+ -. Check status of the Pod inside Replication Controller: -+ -[source, text] ----- -./cluster/kubectl.sh get po -NAME READY STATUS RESTARTS AGE -mysql-pod 1/1 Running 0 1h -wildfly-rc-w2kk5 1/1 Running 0 6m ----- -+ -. Get IP address of the Pod: -+ -[source, text] ----- -./cluster/kubectl.sh get -o template po wildfly-rc-w2kk5 --template={{.status.podIP}} -10.246.1.23 ----- - -[[Access_Kubernetes_Application_Minion]] -#### Access the application (using minion) - -. Log in to minion and access the application: -+ -[source, text] ----- -vagrant ssh minion-1 -Last login: Thu Jul 16 00:24:36 2015 from 10.0.2.2 -[vagrant@kubernetes-minion-1 ~]$ curl http://10.246.1.23:8080/employees/resources/employees/ -1Penny2Sheldon3Amy4Leonard5Bernadette6Raj7Howard8Priya ----- - -[[Access_Kubernetes_Application_Proxy]] -#### Access the application (using proxy) - -Send a PR for https://github.com/javaee-samples/docker-java/issues/80 - -### Deploy Java EE Application (one configuration file) - -Kubernetes allow multiple resources to be specified in a single configuration file. This allows to create a "`Kubernetes Application`" that can consists of multiple resources easily. - -Previous section showed how to deploy the Java EE application using multiple configuration files. This application can be delpoyed using a single configuration file as well. - -. Start the application using the configuration file: -+ -[source, yaml] -.... -apiVersion: v1 -kind: Pod -metadata: - name: mysql-pod - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - containers: - - - name: mysql - image: mysql:latest - env: - - - name: "MYSQL_USER" - value: "mysql" - - - name: "MYSQL_PASSWORD" - value: "mysql" - - - name: "MYSQL_DATABASE" - value: "sample" - - - name: "MYSQL_ROOT_PASSWORD" - value: "supersecret" - ports: - - - containerPort: 3306 ----- -apiVersion: v1 -kind: Service -metadata: - name: mysql-service - labels: - name: mysql-pod - context: docker-k8s-lab -spec: - ports: - # the port that this service should serve on - - port: 3306 - # label keys and values that must match in order to receive traffic for this service - selector: - name: mysql-pod - context: docker-k8s-lab ----- -apiVersion: v1 -kind: ReplicationController -metadata: - name: wildfly-rc - labels: - name: wildfly - context: docker-k8s-lab -spec: - replicas: 1 - template: - metadata: - labels: - name: wildfly - spec: - containers: - - name: wildfly-rc-pod - image: arungupta/wildfly-mysql-javaee7:k8s - ports: - - containerPort: 8080 -.... -+ -Notice that each section, one each for MySQL Pod, MySQL Service, and WildFly Replication Controller, is separated by `----`. -+ -. Start the application: -+ -[source, text] ----- -./cluster/kubectl.sh create -f ../../attendees/kubernetes/app.yaml -pods/mysql-pod -services/mysql-service -replicationcontrollers/wildfly-rc ----- -+ -. Access the application using <> or <>. - -### Rescheduling Pods - -Replication Controller ensures that specified number of pod "`replicas`" are running at any one time. If there are too many, the replication controller kills some pods. If there are too few, it starts more. - -WildFly Replication Controller is already running with one Pod. Lets delete this Pod and see how a new Pod is automatically rescheduled. - -. Find the Pod's name: -+ -[source, text] ----- -./cluster/kubectl.sh get po -NAME READY STATUS RESTARTS AGE -wildfly-rc-w2kk5 1/1 Running 0 6m ----- -+ -. Delete the Pod: -+ -[source, text] ----- -./cluster/kubectl.sh delete po wildfly-rc-w2kk5 -pods/wildfly-rc-w2kk5 ----- -+ -Status of the Pods can be seen in another shell: -+ -[source, text] ----- -./cluster/kubectl.sh get -w po -NAME READY STATUS RESTARTS AGE -wildfly-rc-w2kk5 1/1 Running 0 2m -NAME READY STATUS RESTARTS AGE -wildfly-rc-xz6wu 0/1 Pending 0 2s -wildfly-rc-xz6wu 0/1 Pending 0 2s -wildfly-rc-xz6wu 0/1 Pending 0 12s -wildfly-rc-xz6wu 0/1 Running 0 14s -wildfly-rc-xz6wu 1/1 Running 0 22s ----- -+ -Notice how Pod with name "`wildfly-rc-w2kk5`" was deleted and a new Pod with the name "`wildfly-rc-xz6wu`" was created. - -### Scaling Pods - -Replication Controller allows dynamic scaling up and down of Pods. - -. Scale up the number of Pods: -+ -[source, text] ----- -./cluster/kubectl.sh scale --replicas=2 rc wildfly-rc -scaled ----- -+ -. Status of the Pods can be seen in another shell: -+ -[source, text] ----- -./cluster/kubectl.sh get -w po -NAME READY STATUS RESTARTS AGE -wildfly-rc-bgtkg 1/1 Running 0 3m -NAME READY STATUS RESTARTS AGE -wildfly-rc-bymu7 0/1 Pending 0 2s -wildfly-rc-bymu7 0/1 Pending 0 2s -wildfly-rc-bymu7 0/1 Pending 0 2s -wildfly-rc-bymu7 0/1 Running 0 3s -wildfly-rc-bymu7 1/1 Running 0 12s ----- -+ -Notice a new Pod with the name "`wildfly-rc-bymu7`" is created. -+ -. Scale down the number of Pods: -+ -[source, text] ----- -./cluster/kubectl.sh scale --replicas=1 rc wildfly-rc -scaled ----- -+ -. Status of the Pods using `-w` is not shown correctly https://github.com/GoogleCloudPlatform/kubernetes/issues/11338[#11338]. But status of the Pods can be seen correctly as: -+ -[source, text] ----- -./cluster/kubectl.sh get po -NAME READY STATUS RESTARTS AGE -wildfly-rc-bgtkg 1/1 Running 0 9m ----- -+ -Notice only one Pod is running now. - -### Application Logs - -. Get list of the Pods: -+ -[source, text] ----- -./cluster/kubectl.sh get po -NAME READY STATUS RESTARTS AGE -mysql-pod 1/1 Running 0 18h -wildfly-rc-w2kk5 1/1 Running 0 16h ----- -+ -. Get logs for the WildFly Pod: -+ -[source, text] ----- -./cluster/kubectl.sh logs wildfly-rc-w2kk5 -=> Starting WildFly server -=> Waiting for the server to boot -========================================================================= - - JBoss Bootstrap Environment - - JBOSS_HOME: /opt/jboss/wildfly - - . . . ----- - -Alternatively, the logs can also be seen by logging into the minion: - -. Log in to Minion-1 VM: -+ -[source, text] ----- -> vagrant ssh minion-1 -Last login: Fri Jun 5 23:01:36 2015 from 10.0.2.2 -[vagrant@kubernetes-minion-1 ~]$ ----- -+ -. Log in as root: -+ -[source, text] ----- -[vagrant@kubernetes-minion-1 ~]$ su - -Password: -[root@kubernetes-minion-1 ~]# ----- -+ -Default root password for VM images created by Vagrant is '`vagrant`'. -+ -. See the list of Docker containers running on this VM: -+ -[source, text] ----- -docker ps ----- -+ -. View WildFly log as: -+ -[source, text] ----- -docker logs $(docker ps | grep arungupta/wildfly | awk '{print $1}') ----- -+ -. View MySQL log as: -+ -[source, text] ----- -docker logs ----- - -### Delete Kubernetes Resources - -Individual resources (service, replication controller, or pod) can be deleted by using `delete` command instead of `create` command. Alternatively, all services and replication controllers can be deleted using a label as: - -[source, text] ----- -kubectl delete -l se,po context=docker-k8s-lab ----- - -### Stop Kubernetes Cluster - -[source, text] ----- -> ./cluster/kube-down.sh -Bringing down cluster using provider: vagrant -==> minion-1: Forcing shutdown of VM... -==> minion-1: Destroying VM and associated drives... -==> master: Forcing shutdown of VM... -==> master: Destroying VM and associated drives... -Done ----- - -### Debug Kubernetes Master - -. Log in to the master as: -+ -[source, text] ----- -vagrant ssh master -Last login: Wed Jul 15 20:36:32 2015 from 10.0.2.2 -[vagrant@kubernetes-master ~]$ ----- -+ -. Log in as root: -+ -[source, text] ----- -[vagrant@kubernetes-master ~]$ su - -Password: -[root@kubernetes-master ~]# ----- -+ -Default root password for VM images created by Vagrant is '`vagrant`'. -+ -. Check the containers running on master: -+ -[source, text] ----- -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -dc59a764953c gcr.io/google_containers/etcd:2.0.12 "/bin/sh -c '/usr/lo 20 hours ago Up 20 hours k8s_etcd-container.fa2ab1d9_etcd-server-kubernetes-master_default_7b64ecafde589b94a342982699601a19_2b69c4d5 -b722e22d3ddb gcr.io/google_containers/kube-scheduler:d1107ff3b8fcdcbf5a9d78d9d6dbafb1 "/bin/sh -c '/usr/lo 20 hours ago Up 20 hours k8s_kube-scheduler.7501c229_kube-scheduler-kubernetes-master_default_98b354f725c1589ea5a12119795546ae_b81b9740 -38a73e342866 gcr.io/google_containers/kube-controller-manager:fafaf8100ccc963e643b55e35386d713 "/bin/sh -c '/usr/lo 20 hours ago Up 20 hours k8s_kube-controller-manager.db050993_kube-controller-manager-kubernetes-master_default_f5c25224fbfb2de87e1e5c35e6b3a293_dcd4cb5d -01001de6409e gcr.io/google_containers/kube-apiserver:cff9e185796caa8b281e7d961aea828b "/bin/sh -c '/usr/lo 20 hours ago Up 20 hours k8s_kube-apiserver.7e06f4e1_kube-apiserver-kubernetes-master_default_829f8c23fd5fc7951253cac7618447fc_b39c0a5d -0f8ccb144ece gcr.io/google_containers/pause:0.8.0 "/pause" 20 hours ago Up 20 hours k8s_POD.e4cc795_kube-scheduler-kubernetes-master_default_98b354f725c1589ea5a12119795546ae_eb1efcac -0b8f527456c0 gcr.io/google_containers/pause:0.8.0 "/pause" 20 hours ago Up 20 hours k8s_POD.e4cc795_kube-apiserver-kubernetes-master_default_829f8c23fd5fc7951253cac7618447fc_5dd4dee7 -39d9c41ab1a2 gcr.io/google_containers/pause:0.8.0 "/pause" 20 hours ago Up 20 hours k8s_POD.e4cc795_kube-controller-manager-kubernetes-master_default_f5c25224fbfb2de87e1e5c35e6b3a293_522972ae -d970ddff7046 gcr.io/google_containers/pause:0.8.0 "/pause" 20 hours ago Up 20 hours k8s_POD.e4cc795_etcd-server-kubernetes-master_default_7b64ecafde589b94a342982699601a19_fa75b27f ----- diff --git a/chapters/docker-lattice.adoc b/chapters/docker-lattice.adoc deleted file mode 100644 index 6cba251..0000000 --- a/chapters/docker-lattice.adoc +++ /dev/null @@ -1,34 +0,0 @@ -## Java EE Application on Lattice Cluster - -[quote, github.com/cloudfoundry-incubator/lattice] -Lattice is an open source project for running containerized workloads on a cluster. Lattice bundles up http load-balancing, a cluster scheduler, log aggregation/streaming and health management into an easy-to-deploy and easy-to-use package. - -*How is it related to Docker?* - -ADD DETAILS HERE - -### Key Components - -### Lattice Cluster - -#### Start Lattice Cluster - -#### Verify Lattice Cluster - -### Deploy Java EE Application - -#### Start MySQL Container - -#### Start WildFly Container - -#### Access the application - -### Rescheduling Containers - -### Scaling Containers - -### Application Logs - -### Stop Lattice Cluster - -### Debug Lattice Cluster diff --git a/chapters/docker-maven.adoc b/chapters/docker-maven.adoc deleted file mode 100644 index e51d269..0000000 --- a/chapters/docker-maven.adoc +++ /dev/null @@ -1,124 +0,0 @@ -## Docker Maven Plugin - -Maven plugin allows you to manage Docker images and containers from `pom.xml`. It comes with predefined goals: - -[options="header"] -|==== -|Goal | Description -| `docker:start` | Create and start containers -| `docker:stop` | Stop and destroy containers -| `docker:build` | Build images -| `docker:push` | Push images to a registry -| `docker:remove` | Remove images from local docker host -| `docker:logs` | Show container logs -|==== - -### Run Java EE Application - -. Clone the workspace as: - - git clone https://github.com/javaee-samples/javaee7-docker-maven.git - -. Build the image as: - - mvn package -Pdocker - -. Verify the image as: -+ -[source, text] ----- -docker images -REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE -arungupta/javaee7-docker-maven latest 2e51b3fca40f 4 seconds ago 581.5 MB ----- -+ -. Run the container as: - - mvn install -Pdocker - -. Access your application at http://dockerhost:8080/javaee7-docker-maven/resources/persons. It shows the output as: -+ -[source, xml] ----- -curl http://dockerhost:8080/javaee7-docker-maven/resources/persons -PennyLeonardSheldonAmyHowardBernadetteRajPriya ----- - -### Understand Plugin Configuration - -`pom.xml` is updated to include docker-maven-plugin as: - -[source, xml] ----- - - org.jolokia - docker-maven-plugin - 0.11.5 - - - - user - arungupta/javaee7-docker-maven - - arungupta/wildfly:8.2 - - assembly.xml - / - - - 8080 - - - - - 8080:8080 - - - - - - - - docker:build - package - - build - - - - docker:start - install - - start - - - - ----- - -Each image configuration has three parts: - -. Image name and alias -. `` that defines how the image is created. Base image, build artifacts and their dependencies, ports to be exposed, etc to be included in the image are specified here. http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html[Assembly descriptor format] is used to specify the artifacts to be included and is defined in the `src/main/docker` directory. -+ -`assembly.xml` in our case looks like: -+ -[source, xml] ----- - - javaee7-docker-maven - - - - org.javaee7.sample:javaee7-docker-maven - - /opt/jboss/wildfly/standalone/deployments/ - javaee7-docker-maven.war - - - ----- -+ -. `` that defines how the container is run. Ports that need to be exposed are specified here. - -In addition, `package` phase is tied to `docker:build` goal and `install` phase is tied to `docker:start` goal. diff --git a/chapters/docker-mesos.adoc b/chapters/docker-mesos.adoc deleted file mode 100644 index 0f835e8..0000000 --- a/chapters/docker-mesos.adoc +++ /dev/null @@ -1,38 +0,0 @@ -## Java EE Application on Mesos + Marathon Cluster - -[quote, mesos.apache.org/] -Apache Mesos abstracts CPU, memory, storage, and other compute resources away from machines (physical or virtual), enabling fault-tolerant and elastic distributed systems to easily be built and run effectively. - -Mesos is built using the same principles as the Linux kernel, only at a different level of abstraction. The Mesos kernel runs on every machine and provides applications (e.g., Hadoop, Spark, Kafka, Elastic Search) with API’s for resource management and scheduling across entire datacenter and cloud environments. - -TODO: Add Solomon's quote about Mesos production for Docker - -*How is it related to Docker?* - -ADD DETAILS HERE - -### Key Components - -### Mesos Cluster - -#### Start Mesos Cluster - -#### Verify Mesos Cluster - -### Deploy Java EE Application - -#### Start MySQL Container - -#### Start WildFly Container - -#### Access the application - -### Rescheduling Containers - -### Scaling Containers - -### Application Logs - -### Stop Mesos Cluster - -### Debug Mesos Cluster diff --git a/chapters/docker-mod-cluster.adoc b/chapters/docker-mod-cluster.adoc deleted file mode 100644 index 6455fa2..0000000 --- a/chapters/docker-mod-cluster.adoc +++ /dev/null @@ -1,65 +0,0 @@ -[[JavaEE_Application_Docker_Cluster]] -## Java EE Application on Mod Cluster - -A frequent requirement for Java EE based applications is running them on a cluster of application server. While setup and test can be complicated on developer machines, this is where Docker can play to it's full potential. With the help of images and automatic port mapping, we're ready to test Ticket Monster on a couple of WildFly instances and add and remove them randomly. - -The diagram below shows what will be achieved in this section: - -.Standalone Cluster with WildFly and mod_cluster -image::wildfly_cluster1.png[] - -. Start Apache HTTPD server -+ -[source, text] ----- -docker run -d --name modcluster -p 80:80 classroom.example.com:5000/mod_cluster ----- -+ -. Open http://dockerhost/mod_cluster_manager in your browser to see the empty console as: -+ -.Apache HTTPD runing mod_cluster_manager interface -image::wildfly_cluster2.png[] -+ -. Start Postgres database container, if not already running: -+ -[source, text] ----- -docker run --name db -d -p 5432:5432 -e POSTGRES_USER=ticketmonster -e POSTGRES_PASSWORD=ticketmonster-docker classroom.example.com:5000/postgres ----- -+ -. Start the first WildFly instance: -+ -[source, text] ----- -docker run -d --name server1 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly ----- -+ -Besides linking the database container using `--link db:db`, we also link the ``modcluster'' container. This should be done rather quickly and if you now revisit the http://dockerhost/mod_cluster_manager/[mod_cluster_manager] in your browser, then you can see that the first server was registered with the loadbalancer: -+ -.First WildFly instance registered with Load Balancer -image::wildfly_cluster3.png[] -+ -. To make sure the Ticket Monster application is also running just visit http://dockerhost/ticket-monster and you will be presented with the Ticket Monster welcome screen. -+ -.Clustered Ticket Monster Application -image::wildfly_cluster4.png[] -+ -. Start as many WildFly instances as you want (and your computer memory can handle): -+ -[source, text] ----- -docker run -d --name server2 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly -docker run -d --name server3 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly -docker run -d --name server4 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly ----- -+ -. Stop some servers: -+ -[source, text] ----- -docker stop server1 -docker stop server3 ----- -+ -Ensure that the application is still accessible at http://dockerhost/ticket-monster. - diff --git a/chapters/docker-netbeans.adoc b/chapters/docker-netbeans.adoc deleted file mode 100644 index a4d7889..0000000 --- a/chapters/docker-netbeans.adoc +++ /dev/null @@ -1 +0,0 @@ -## Docker Tools in NetBeans \ No newline at end of file diff --git a/chapters/docker-openshift.adoc b/chapters/docker-openshift.adoc deleted file mode 100644 index 88219f4..0000000 --- a/chapters/docker-openshift.adoc +++ /dev/null @@ -1,58 +0,0 @@ -## OpenShift v3 (Optional Part, No Windows?) - -[quote, github.com/openshift/origin] -OpenShift adds developer and operational centric tools on top of Kubernetes to enable rapid application development, easy deployment and scaling, and long-term lifecycle maintenance for small and large teams and applications. - -OpenShift is Red Hat’s open source PaaS platform. OpenShift v3 (due to be released this year) will provide a holistic experience on running your microservices using Docker and Kubernetes. In a classic Red Hat way, all the work is done in the open source at OpenShift Origin. This will also drive the next major release of OpenShift Online and OpenShift Enterprise. - -OpenShift v3 uses a new platform stack that is using plenty of community projects where Red Hat contributes such as Fedora, Centos, Docker, Project Atomic, Kubernetes, and OpenStack. OpenShift v3 Platform Combines Docker, Kubernetes, Atomic and More explain this platform stack in detail. - -image::openshiftv3-stack.png[] - -### Download and Run OpenShift Origin - -OpenShift Origin is available as a Docker container. It has all of the software prebuilt and pre-installed, but you do need to do a few things to get it going. - -. Create a `/var/lib/openshift` folder on your Docker host. This volume will be mounted in the container to hold any data such that it is preserved after restart. -+ -[source, text] ----- -docker-machine ssh lab "mkdir /var/lib/openshift" ----- -+ -. Download and run the OpenShift Origin container as: -+ -[source, text] ----- -$ docker run -d --name "openshift-origin" --net=host --privileged \ --v /var/run/docker.sock:/var/run/docker.sock \ --v /var/lib/openshift:/var/lib/openshift \ -classroom.example.com:5000/openshift start ----- -+ -. Check that the container is running: -+ -[source, text] ----- -> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -df29f4cdff9e openshift/origin:latest "/usr/bin/openshift 57 seconds ago Up 57 seconds openshift-origin ----- - -### Run Java EE Application - -Here is the deployment diagram of our application: - -image::openshiftv3-wildfly-mysql-deployment.png[] - -. WildFly and MySQL are running on separate pods. -. Each of them is wrapped in a Replication Controller to enable simplified scaling. -. Each Replication Controller is published as a Service. -. WildFly talks to the MySQL service, as opposed to directly to the pod. This is important as Pods, and IP addresses assigned to them, are ephemeral. - -Lets get started! - -. Docker host is already configured to trust insecure registry service. This registry will be used to push images for build/test/deploy cycle. - - -http://blog.arungupta.me/openshift-v3-getting-started-javaee7-wildfly-mysql/ diff --git a/chapters/docker-preface.adoc b/chapters/docker-preface.adoc deleted file mode 100644 index 85bf477..0000000 --- a/chapters/docker-preface.adoc +++ /dev/null @@ -1,9 +0,0 @@ -## Preface - -Containers are enabling developers to package their applications (and underlying dependencies) in new ways that are portable and work consistently everywhere? On your machine, in production, in your data center, and in the cloud. And Docker has become the de facto standard for those portable containers in the cloud. - -Docker is the developer-friendly Linux container technology that enables creation of your stack: OS, JVM, app server, app, and all your custom configuration. So with all it offers, how comfortable are you and your team taking Docker from development to production? Are you hearing developers say, “But it works on my machine!” when code breaks in production? - -This lab offers developers an intro-level, hands-on session with Docker, from installation, to exploring Docker Hub, to crafting their own images, to adding Java apps and running custom containers. It will also explain how to use Swarm to orchesorchestrate these containers together. This is a BYOL (bring your own laptop) session, so bring your Windows, OSX, or Linux laptop and be ready to dig into a tool that promises to be at the forefront of our industry for some time to come. - -NOTE: Latest content of this lab is always at https://github.com/javaee-samples/docker-java \ No newline at end of file diff --git a/chapters/docker-references.adoc b/chapters/docker-references.adoc deleted file mode 100644 index b2be768..0000000 --- a/chapters/docker-references.adoc +++ /dev/null @@ -1,6 +0,0 @@ -## References - -. Docker Docs: http://docs.docker.com -. Kubernetes Docs: https://github.com/kubernetes/kubernetes/tree/master/docs -. JBoss and Docker: http://www.jboss.org/docker/ -. Latest lab content: https://github.com/javaee-samples/docker-java diff --git a/chapters/docker-setup.adoc b/chapters/docker-setup.adoc deleted file mode 100644 index 15366c9..0000000 --- a/chapters/docker-setup.adoc +++ /dev/null @@ -1,153 +0,0 @@ -## Setup Environments - -This section describes what, how, and where to install the software needed for this lab. This lab is designed for a BYOL (Brying Your Own Laptop) style hands-on-lab. - -### Hardware - -. Operating System: Mac OS X (10.8 or later), Windows 7 (SP1), Fedora (21 or later) -. Memory: At least 4 GB+, preferred 8 GB - -### Software - -. Java: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[Oracle JDK 8u45] -. Web Browser -.. https://www.google.com/chrome/browser/desktop/[Chrome] -.. link:http://www.getfirefox.com[Firefox] - -### Git Client - -Install Git Client as explained at: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git - -### Maven - -. Download Apache Maven from https://maven.apache.org/download.cgi. -. Unzip to a directory of your choice and add it to the `PATH`. - -### VirtualBox - -Docker currently runs natively on Linux. It can be configured to run in a virtual machine on Mac or Windows. This is why Virtualbox is a requirement for Mac or Windows. - -Downloads are available from https://www.virtualbox.org/. - -Virtual Box 5.0.0 does not allow Kubernetes cluster to be started: https://github.com/kubernetes/kubernetes/issues/12614. Make sure to download VirtualBox 4.3.30[https://www.virtualbox.org/wiki/Download_Old_Builds_4_3]. - -[WARNING] -==== -Linux Users - -. Have your kernel updated -. Users should have the GNU compiler, build and header files for your current Linux kernel -. Create a `/usr/src/linux` link to the current kernel source -==== - -### Vagrant - -Download Vagrant from https://www.vagrantup.com/downloads.html and install. - -### Docker Machine - -Docker Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them. - -[source, text] ----- -# Mac -curl -L https://github.com/docker/machine/releases/download/v0.4.0/docker-machine_darwin-amd64 > /usr/local/bin/docker-machine -chmod +x /usr/local/bin/docker-machine - -# Linux -curl -L https://github.com/docker/machine/releases/download/v0.4.0/docker-machine_linux-amd64 > /usr/local/bin/docker-machine -chmod +x /usr/local/bin/docker-machine - -#Windows -curl https://github.com/docker/machine/releases/download/v0.4.0/docker-machine.exe ----- - -### Create Lab Docker Host - -. Create Docker Host to be used in the lab: -+ -[source, text] ----- -docker-machine create --driver=virtualbox lab -eval "$(docker-machine env lab)" ----- -+ -. To make it easier to start/stop the containers, an entry is added into the host mapping table of your operating system. Find out the IP address of your machine: -+ -[source, text] ----- -docker-machine ip lab ----- -+ -This will provide the IP address associated with the Docker Machine created earlier. -+ -. Edit `/etc/hosts` (Mac OS or Linux) or `C:\Windows\System32\drivers\etc\hosts` (Windows) and add: -+ -[source, text] ----- - dockerhost ----- - -### Docker Client - -Docker Client is used to communicate with Docker Host. - -[source, text] ----- -# Mac -curl -L https://get.docker.com/builds/Darwin/x86_64/docker-latest > /usr/local/bin/docker -chmod +x /usr/local/bin/docker - -# Linux -curl -L https://get.docker.com/builds/Linux/x86_64/docker-latest > docker-latest-linux -chmod +x /usr/local/bin/docker - -# Windows -curl -L http://test.docker.com.s3.amazonaws.com/builds/Windows/x86_64/docker-1.7.0.exe -o docker.exe ----- - -### Kubernetes - -. Download Kubernetes (1.0.1) from https://github.com/kubernetes/kubernetes/releases/download/v1.0.1/kubernetes.tar.gz. -. Extract the archive and install it by: - -[source, text] ----- -export KUBERNETES_PROVIDER=vagrant -cd kubernetes -./cluster/kube-up.sh ----- - -NOTE: Kubernetes 1.0.1 is the only version verified to work with Virtual Box. More details at: https://github.com/kubernetes/kubernetes/issues/12614 - -### WildFly - -. Download WildFly 9.0 from http://download.jboss.org/wildfly/9.0.0.Final/wildfly-9.0.0.Final.zip. -. Install it by extracting the archive. - -### JBoss Developer Studio 9 - Beta 2 - -To install JBoss Developer Studio stand-alone, complete the following steps: - -. Download http://tools.jboss.org/downloads/devstudio/mars/9.0.0.Beta2.html[9.0.0 Beta 2] or -https://devstudio.redhat.com/9.0/snapshots/builds/devstudio.product_master/latest/installer/[Latest Nightly]. -. Start the installer as: -+ -[source, text] ----- -java -jar ----- -+ -Follow the on-screen instructions to complete the installation process. - -### Pull Docker images - -[source, text] ----- -docker pull jboss/wildfly -docker pull arungupta/wildfly-management -docker pull arungupta/javaee7-hol -docker pull mysql -docker pull swarm -docker pull arungupta/wildfly-mysql-javaee7 ----- diff --git a/chapters/docker-swarm.adoc b/chapters/docker-swarm.adoc deleted file mode 100644 index 2c45e00..0000000 --- a/chapters/docker-swarm.adoc +++ /dev/null @@ -1,355 +0,0 @@ -## Java EE Application on Docker Swarm Cluster - -Docker Swarm is native clustering for Docker. It allows you create and access to a pool of Docker hosts using the full suite of Docker tools. Because Docker Swarm serves the standard Docker API, any tool that already communicates with a Docker daemon can use Swarm to transparently scale to multiple hosts - -### Key Components of Docker Swarm - -.Key Components of Docker Swarm -image::docker-swarm-components.png[] - -*Swarm Manager*: Docker Swarm has a Manager, that is a pre-defined Docker Host, and is a single point for all administration. The swarm manager orchestrates and schedules containers on the entire cluster. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with https://github.com/docker/swarm/issues/598[#598]. - -*Swarm Nodes*: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a Docker Swarm agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node. - -*Scheduler Strategy*: Different scheduler strategies ("`binpack`", "`spread`" (default), and "`random`") can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm. - -*Node Discovery Service*: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and ZooKeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and https://github.com/docker/swarm/issues/660[#660] will discuss this. - -**Standard Docker API:** Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means that if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster. - -There are lots of other concepts but these are the main ones. - -### Create a Docker Swarm Cluster - -. The easiest way of using Swarm is, by using the official Docker image: - - docker run swarm create -+ -This command returns a discovery token, referred as in this document, and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub. -+ -It shows the output as: -+ -[source, text] ----- -docker run swarm create -Unable to find image 'swarm:latest' locally -latest: Pulling from swarm -55b38848634f: Pull complete -fd7bc7d11a30: Pull complete -db039e91413f: Pull complete -1e5a49ab6458: Pull complete -5d9ce3cdadc7: Pull complete -1f26e949f933: Pull complete -e08948058bed: Already exists -swarm:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. -Digest: sha256:0e417fe3f7f2c7683599b94852e4308d1f426c82917223fccf4c1c4a4eddb8ef -Status: Downloaded newer image for swarm:latest -1d528bf0568099a452fef5c029f39b85 ----- -+ -The last line is the . -+ -NOTE: Make sure to note this cluster id now as there is no means to list it later. This should be fixed with https://github.com/docker/swarm/issues/661[#661]. -+ -. Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let's create a Swarm Master next: -+ -[source, text] ----- -docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token:// swarm-master ----- -+ -Replace `` with the cluster id obtained in the previous step. -+ -`--swarm` configures the machine with Swarm, `--swarm-master` configures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster. -+ -. Connect to this newly created master and find some more information about it: -+ -[source, text] ----- -eval "$(docker-machine env swarm-master)" -docker info ----- -+ -NOTE: If you're on Windows, use the `docker-machine env swarm-master` command only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/". -+ -This will show the output as: -+ -[source, text] ----- -> docker info -Containers: 2 -Images: 7 -Storage Driver: aufs - Root Dir: /mnt/sda1/var/lib/docker/aufs - Backing Filesystem: extfs - Dirs: 11 - Dirperm1 Supported: true -Execution Driver: native-0.2 -Logging Driver: json-file -Kernel Version: 4.0.5-boot2docker -Operating System: Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015 -CPUs: 1 -Total Memory: 996.2 MiB -Name: swarm-master -ID: DLFR:OQ3E:B5P6:HFFD:VKLI:IOLU:URNG:HML5:UHJF:6JCL:ITFH:DS6J -Debug mode (server): true -File Descriptors: 22 -Goroutines: 36 -System Time: 2015-07-11T00:16:34.29965306Z -EventsListeners: 1 -Init SHA1: -Init Path: /usr/local/bin/docker -Docker Root Dir: /mnt/sda1/var/lib/docker -Username: arungupta -Registry: https://index.docker.io/v1/ -Labels: - provider=virtualbox ----- -+ -. Create a Swarm node - - docker-machine create -d virtualbox --swarm --swarm-discovery token:// swarm-node-01 -+ -Replace `` with the cluster id obtained in an earlier step. -+ -Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by `--swarm-discovery token://...` and specifying the cluster id obtained earlier. -. To make it a real cluster, let's create a second node: - - docker-machine create -d virtualbox --swarm --swarm-discovery token:// swarm-node-02 -+ -Replace `` with the cluster id obtained in the previous step. - -. List all the nodes created so far: - - docker-machine ls -+ -This shows the output similar to the one below: -+ -[source, text] ----- -docker-machine ls -NAME ACTIVE DRIVER STATE URL SWARM -lab virtualbox Running tcp://192.168.99.101:2376 -summit2015 virtualbox Running tcp://192.168.99.100:2376 -swarm-master * virtualbox Running tcp://192.168.99.102:2376 swarm-master (master) -swarm-node-01 virtualbox Running tcp://192.168.99.103:2376 swarm-master -swarm-node-02 virtualbox Running tcp://192.168.99.104:2376 swarm-master ----- -+ -The machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example, "`lab`" and "`summit2015`" are standalone machines where as all other machines are part of the "`swarm-master`" cluster. The Swarm master is also identified by (master) in the SWARM column. -+ -. Connect to the Swarm cluster and find some information about it: - - eval "$(docker-machine env --swarm swarm-master)" - docker info -+ -This shows the output as: -+ -[source, text] ----- -> docker info -Containers: 4 -Images: 3 -Role: primary -Strategy: spread -Filters: affinity, health, constraint, port, dependency -Nodes: 3 - swarm-master: 192.168.99.102:2376 - └ Containers: 2 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-01: 192.168.99.103:2376 - └ Containers: 1 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-02: 192.168.99.104:2376 - └ Containers: 1 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs -CPUs: 3 -Total Memory: 3.065 GiB ----- -+ -There are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers. -+ -. List nodes in the cluster with the following command: -+ -[source, text] ----- -docker run swarm list token:// ----- -+ -This shows the output as: -+ -[source, text] ----- -> docker run swarm list token://1d528bf0568099a452fef5c029f39b85 -192.168.99.103:2376 -192.168.99.104:2376 -192.168.99.102:2376 ----- - -### Deploy Java EE Application to Docker Swarm Cluster - -The complete cluster is in place now, and we need to deploy the Java EE application to it. - -Swarm takes care for the distribution of deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in <>. - -. Start MySQL server as: -+ -[source, text] ----- -docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql ----- -+ -`-e` define environment variables that are read by the database at startup and allow us to access the database with this user and password. -+ -. Start WildFly and deploy Java EE 7 application as: -+ -[source, text] ----- -docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7 ----- -+ -This is using the https://docs.docker.com/userguide/dockerlinks/[Docker Container Linking] explained earlier. -+ -. Check state of the cluster as: -+ -[source, text] ----- -> docker info -Containers: 7 -Images: 5 -Role: primary -Strategy: spread -Filters: affinity, health, constraint, port, dependency -Nodes: 3 - swarm-master: 192.168.99.102:2376 - └ Containers: 2 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-01: 192.168.99.103:2376 - └ Containers: 2 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-02: 192.168.99.104:2376 - └ Containers: 3 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs -CPUs: 3 -Total Memory: 3.065 GiB ----- -+ -"`swarm-node-02`" is running three containers and so lets look at the list of running containers: -+ -[source, text] ----- -> eval "$(docker-machine env swarm-node-02)" -> docker ps -a -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -805f3587f5df arungupta/wildfly-mysql-javaee7 "/opt/jboss/wildfly/ About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp mywildfly -ababc544df97 mysql "/entrypoint.sh mysq 5 minutes ago Up 5 minutes 0.0.0.0:3306->3306/tcp mysqldb -45b015bc79f4 swarm:latest "/swarm join --addr 17 minutes ago Up 17 minutes 2375/tcp swarm-agent ----- -+ -. Access the application as: -+ -[source, text] ----- -curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees ----- -+ -to see the output as: -+ -[source, xml] ----- -1Penny2Sheldon3Amy4Leonard5Bernadette6Raj7Howard8Priya ----- - -### Deploy Java EE Application to Docker Swarm Cluster using Docker Compose - -<> explains how multi container applications can be easily started using Docker Compose. - -. Connect to '`swarm-node-02`': - - eval "$(docker-machine env swarm-node-02)" - -. Stop the MySQL and WildFly containers: - - docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f - docker ps -a | grep mysql | awk '{print $1}' | xargs docker rm -f - -. Use the `docker-compose.yml` file explained in <> to start the containers as: - - docker-compose up -d - Creating wildflymysqljavaee7_mysqldb_1... - Creating wildflymysqljavaee7_mywildfly_1... - -. Check the containers running in the cluster as: - - eval "$(docker-machine env --swarm swarm-master)" - docker info -+ -to see the output as: -+ -[source, text] ----- -docker info -Containers: 7 -Images: 5 -Role: primary -Strategy: spread -Filters: affinity, health, constraint, port, dependency -Nodes: 3 - swarm-master: 192.168.99.102:2376 - └ Containers: 2 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-01: 192.168.99.103:2376 - └ Containers: 2 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs - swarm-node-02: 192.168.99.104:2376 - └ Containers: 3 - └ Reserved CPUs: 0 / 1 - └ Reserved Memory: 0 B / 1.022 GiB - └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs -CPUs: 3 -Total Memory: 3.065 GiB ----- -+ -. Connect to '`swarm-node-02`' again: - - eval "$(docker-machine env swarm-node-02)" -+ -and see the list of running containers as: -+ -[source, text] ----- -docker ps -a -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -b1e7d9bd2c09 arungupta/wildfly-mysql-javaee7 "/opt/jboss/wildfly/ 38 seconds ago Up 37 seconds 0.0.0.0:8080->8080/tcp wildflymysqljavaee7_mywildfly_1 -ac9c967e4b1d mysql:latest "/entrypoint.sh mysq 38 seconds ago Up 38 seconds 3306/tcp wildflymysqljavaee7_mysqldb_1 -45b015bc79f4 swarm:latest "/swarm join --addr 20 minutes ago Up 20 minutes 2375/tcp swarm-agent ----- - -. Application can then be accessed again using: - - curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees -+ -and shows the output as: -+ -[source, xml] ----- -1Penny2Sheldon3Amy4Leonard5Bernadette6Raj7Howard8Priya ----- - -Add container visualiation using https://github.com/javaee-samples/docker-java/issues/55. diff --git a/chapters/docker-testing.adoc b/chapters/docker-testing.adoc deleted file mode 100644 index 62fa874..0000000 --- a/chapters/docker-testing.adoc +++ /dev/null @@ -1,85 +0,0 @@ -## Test Java EE Applications on Docker - -Testing Java EE applications is a very important aspect. Especially when it comes to in-container tests, http://www.arquillian.org[JBoss Arquillian] is well known to make this very easy for Java EE application servers. Picking up where unit tests leave off, Arquillian handles all the plumbing of container management, deployment and framework initialization so you can focus on the task at hand, writing your tests. - -With Arquillian, you can use http://arquillian.org/modules/wildfly-arquillian-wildfly-remote-container-adapter/[WildFly remote container adapter] and connect to any WildFly instance running in a Docker container. But this wouldn't help with the Docker container lifycycle management. - -http://arquillian.org/modules/cube-extension/[Arquillian Cube], an extension of Arquillian, allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually. This extension allows to start a Docker container with a server installed, deploy the required deployable file within it and execute Arquillian tests. - -The key point here is that if Docker is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before. - -. Check out the workspace: -+ -[source, text] ----- -git clone http://github.com/javaee-samples/javaee-arquillian-cube ----- -+ -. Edit `src/test/resources/arquillian.xml` file and change the IP address specified in `serverUri` property value to point to your Docker host's IP. This can be found out as: -+ -[source, text] ----- -docker-machine ip lab ----- -+ -. Run the tests as: -+ -[source, text] ----- -mvn test ----- -+ -This will create a container using the image defined in `src/test/resources/wildfly/Dockerfile`. The container qualifier in `arquillian.xml` defines the directory name in `src/test/resources` directory. -+ -[NOTE] -==== -A pre-built image can be used by specifying: - - wildfly: - image: jboss/wildfly - -instead of - - wildfly: - buildImage: - dockerfileLocation: src/test/resources/wildfly -==== -+ -By default, the "`cube`" profile is activated and this includes all the required dependencies. -+ -The result is shown as: -+ -[source, text] ----- -Running org.javaee7.sample.PersonDatabaseTest -Jun 16, 2015 9:23:04 AM org.jboss.arquillian.container.impl.MapObject populate -WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.remote.RemoteContainerConfiguration -Unused property entries: {target=wildfly:8.1.0.Final:remote} -Supported property names: [managementAddress, password, managementPort, managementProtocol, username] -Jun 16, 2015 9:23:13 AM org.xnio.Xnio -INFO: XNIO version 3.2.0.Beta4 -Jun 16, 2015 9:23:13 AM org.xnio.nio.NioXnio -INFO: XNIO NIO Implementation Version 3.2.0.Beta4 -Jun 16, 2015 9:23:13 AM org.jboss.remoting3.EndpointImpl -INFO: JBoss Remoting version (unknown) -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.406 sec - in org.javaee7.sample.PersonDatabaseTest - -Results : - -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - -[INFO] ------------------------------------------------------------------------ -[INFO] BUILD SUCCESS -[INFO] ------------------------------------------------------------------------ ----- -+ -. In `arquillian.xml`, add the following property: -+ -[source, xml] ----- -STARTORCONNECT ----- -+ -This bypasses the create/start Cube commands if a Docker Container with the same name is already running on the target system. -+ -This allows you to prestart the containers manually during development and just connect to them to avoid the extra cost of starting the Docker Containers for each test run. This assumes you are not changing the actual definition of the Docker Container itself. diff --git a/chapters/docker-ticket-monster.adoc b/chapters/docker-ticket-monster.adoc deleted file mode 100644 index 709b6fa..0000000 --- a/chapters/docker-ticket-monster.adoc +++ /dev/null @@ -1,270 +0,0 @@ -## Build and Deploy Java EE 6 Application (Ticket Monster) - -http://www.jboss.org/ticket-monster/[Ticket Monster] is an example application that focuses on Java EE6 - JPA 2, CDI, EJB 3.1 and JAX-RS along with HTML5 and jQuery Mobile. It is a moderately complex application that demonstrates how to build modern web applications optimized for mobile & desktop. TicketMonster is representative of an online ticketing broker - providing access to events (e.g. concerts, shows, etc) with an online booking application. - -.TicketMonster architecture -image::ticket-monster_tutorial_architecture.png[] - -The application uses Java EE 6 services to provide business logic and persistence, utilizing technologies such as CDI, EJB 3.1 and JAX-RS, JPA 2. These services back the user-facing booking process, which is implemented using HTML5 and JavaScript, with support for mobile devices through jQuery Mobile. - -[[Build_Application]] -### Build Application - -In order to build the application from source, create a directory and change to it: - -[source, text] ----- -mkdir docker-java/ -cd docker-java/ ----- - -Checkout sources from the git repository. - -[source, text] ----- -ifdef::classroom[git clone -b WildFly-docker-test http://root:dockeradmin@classroom.example.com:10080/root/ticket-monster.git] -ifdef::public[] ----- - -`-b WildFly-docker-test` is a branch of Ticket Monster that contains a ``docker-test'' profile to run Arquillian Cube test. More on this later. - -NOTE: You're free to explore the application. Open it with with the favorite IDE of your choice. Find more background about the use-cases and how the application is designed at http://www.jboss.org/ticket-monster/whatisticketmonster/[Ticket Monster Website]. - -Copy the Maven `lab-settings.xml` file that you have downloaded from the instructor machine and place it inside `docker-java` directory. - -When you're ready, it is time to build the application. Switch to the checkout directory and run maven package. - -[source, text] ----- -cd docker-java/ -mvn -s lab-settings.xml -f ticket-monster/demo/pom.xml -Ppostgresql clean package ----- - -Congratulations! You just build the applications war file. Let's deploy it! - -### Start Database Server - -The application require an application server and a database server. This lab will use WildFly and Postgres for them respectively. - -Start Postgres database as: - -[source, text] ----- -docker run --name db -d -p 5432:5432 -e POSTGRES_USER=ticketmonster -e POSTGRES_PASSWORD=ticketmonster-docker classroom.example.com:5000/postgres ----- - -This command starts a container named ``db'' from the image in your instructor's registry `classroom.example.com:5000/postgres`. As this will not be present locally, it needs to be downloaded first. But you'll have a very quick connection to the instructor registry and this shouldn't take long. - -The two `-e` options define environment variables which are read by the db at startup and allow us to access the database with this user and password. - -Finally, the `-d` option tells docker to start a demon process. Which means, that the console window, you're running this command in, will be available again after it is issued. If you skip this parameter, the console will be directly showing the output from the process. - -`-p` option maps container ports to host ports and allows other containers on our host to access them. - -This starts the database container. It can be confirmed as: - -[source, text] ----- -> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -047bab6a86fe classroom.example.com:5000/postgres:latest "/docker-entrypoint. 42 seconds ago Up 3 seconds 0.0.0.0:5432->5432/tcp db ----- - -Server logs can be viewed as: - -[source, text] ----- -docker logs -f db ----- - -The `-f` flag keeps refreshing the logs and pushes new events directly out to the console. - -### Start Application Server - -Start WildFly server as: - -[source, text] ----- -docker run -d --name wildfly -p 8080:8080 --link db:db -v /Users/youruser/tmp/deployments:/opt/jboss/wildfly/standalone/deployments/:rw classroom.example.com:5000/wildfly ----- - -Make sure to replace `/Users/youruser/tmp/deployments` to a directory on your local machine. Also, make sure this directory already exists. - -This command starts a container named ``wildfly''. `--link` takes two parameters - first is name of the container we're linking to and second is the alias for the link name. - -.Container Linking -[NOTE] -=============================== -Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container. - -In our case, target container (WildFly) can see information about source container (Postgres). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. - -See more about container communication on the Docker website link:https://docs.docker.com/userguide/dockerlinks/[Linking Containers Together] -=============================== - -The `-v` flag maps a directory from the host into the container. This will be the directory to put the deployments. `rw` ensures that the Docker container can write to it. - -WARNING: Windows users, please make sure to use `-v /c/Users/` notation for drive letters. - -Check logs to verify if the server has started. - -[source, text] ----- -docker logs -f wildfly ----- - -And access the http://dockerhost:8080 with your webbrowser to make sure the instance is up and running. - -Now you're ready to deploy the application for the first time. Let's use JBoss Developer Studio for this. - -### Configure JBoss Developer Studio - -Start JBoss Developer Studio, if not already started. - -. Create a server adapter -+ -.Server adapter -image::jbds1.png[] -+ -. Assign or create a WildFly 8.x runtime (changed properties are highlighted.) -+ -.WildFly Runtime Properties -image::jbds2.png[] -+ -. Setup server properties as shown in the following image. -+ -Two properties on the left are automatically propagated from the previous dialog. Additional two properties on the right side are required to disable to keep deployment scanners in sync with the server. -+ -.Server properties -image::jbds3.png[] -+ -. Specify a custom deployment folder on Deployment tab of Server Editor -+ -.Server Editor -image::jbds4.png[] -+ -. Right-click on the newly created server adapter and click ``Start''. -+ -.Start Server -image::jbds5.png[] - -### Deploy Application Using Shared Volumes - -Open Ticket Monster application source code. Right-click on the project, select ``Run on Server'' and chose the previously created server. - -The project runs and displays the start page of Ticket Monster application. - -.Start Server -image::jbds6.png[] - -Congratulations! You've just deployed your first application to WildFly running in a Docker container from JBoss Developer Studio. - -Stop WildFly container when you're done. - -[source, text] ----- -docker stop wildfly ----- - -### Deploy Application Using CLI (OPTIONAL) - -The Command Line Interface (CLI) is a tool for connecting to WildFly instances to manage all tasks from command line environment. Some of the tasks that you can do using the CLI are: - -. Deploy/Undeploy web application in standalone/Domain Mode. -. View all information about the deployed application on runtime. -. Start/Stop/Restart Nodes in respective mode i.e. Standalone/Domain. -. Adding/Deleting resource or subsystems to servers. - -Lets use the CLI to deploy Ticket Monster to WildFly running in the container. - -. CLI needs to be locally installed and comes as part of WildFly. Download WildFly 8.2 from http://classroom.example.com:8082/downloads/wildfly-8.2.0.Final.zip. Unzip into a folder of your choice (e.g. `/Users/arungupta/tools/`). This will create `wildfly-8.2.0.Final` directory here. This folder is named $WIDLFY_HOME from here on. Make sure to add the `/Users/arungupta/tools/wildfly-8.2.0.Final/bin` to your $PATH. -+ -[source, text] ----- -# Windows Example -set PATH=%PATH%;%WILDFLY_HOME%/bin ----- -+ -. Run the ``wildfly-management'' image with fixed port mapping as explained in <>. -. Run the `jboss-cli` command and connect to the WildFly instance. -+ -[source, text] ----- -cd %WIDLFY_HOME%/bin -./jboss-cli.sh --controller=dockerhost:9990 -u=admin -p=docker#admin -c ----- -+ -This will show the output as: -+ -[source, text] ----- -[standalone@dockerhost:9990 /] ----- -+ -. Deploy the application as: -+ -[source, text] ----- -deploy /ticket-monster.war --force ----- - -Now you've sucessfully used the CLI to remote deploy the Ticket Monster application to WildFly running as docker container. - -And again, keep the container running, we're going to look into the last deployment option you have. - -### Deploy Application Using Web Console (OPTIONAL) - -WildFly comes with a web-based administration console. It also relies on the same management APIs that we've already been using via JBoss Developer Tools and the CLI. It does provide a nice web-based way to administrate your instance and if you've already exposed the container ports, you can simply access it via the URL: http://dockerhost:9990 in your web browser. - -.WildFly Web Console -image::console1.png[] - -Username and password credentials are shown in <>. Now navigate through the console and execute the following steps to deploy the application: - -. Go to the ``Deployments'' tab. -. Click on ``Add'' button. -. On ``Step 1/2: Deployment Selection'' screen, select the /ticket-monster.war file on your computer and click ``Next''. This would be `ticket-monster/demo/target/ticket-monster.war` from <>. -. On the ``Step 2/2: Verify Deployment Names'' screen, select ``Enable'' checkbox, and click on ``Save''. - -This will complete the deployment of Ticket Monster using Admin Console. - -### Deploy Application Using Management API (OPTIONAL) - -A standalone WildFly process, process can be configured to listen for remote management requests using its ``native management interface''. The CLI tool that comes with the application server uses this interface, and user can develop custom clients that use it as well. In order to use this, WildFly management interface listen IP needs to be changed from 127.0.0.1 to 0.0.0.0 which basically means, that it is not only listening on the localhost but also on all publicly assigned IP addresses. - -. Start another WildFly instance again: -+ -[source, text] ----- -docker run -d --name wildflymngm -p 8080:8080 -p 9990:9990 --link db:db classroom.example.com:5000/wildfly-management ----- -+ -There is no mapped volume in this case but an additional port exposed. The WildFly image that is used makes it easier for you to play around with the deployment via the management API. It has a tweaked start script which changes the management interface according to the behavior described in the first sentence. -+ -. Create another new server adapter in JBoss Developer Studio. -+ -.Create New Server Adapter -image::jbds7.png[] -+ -. Keep the defaults in the adapter properties. -+ -.Adapter Properties -image::jbds8.png[] -+ -. Set up server properties by specifying the admin credentials (docker#admin). Note, you need to delete the existing password and use this instead: -+ -.Management Login Credentials -image::jbds9.png[] -+ -. Right-click on the newly created server adapter and click ``Start''. Status quickly changes to ``Started, Synchronized'' as shown. -+ -.Synchronized WildFly Server -image::jbds10.png[] -+ -. Right-click on the Ticket Monster project, select ``Run on Server'' and choose this server. The project runs and displays the start page of ticket-monster. -. Stop WildFly when you're done. -+ -[source, text] ----- -docker stop wildflymngm ----- diff --git a/chapters/images/console1.png b/chapters/images/console1.png deleted file mode 100644 index 8f9103c..0000000 Binary files a/chapters/images/console1.png and /dev/null differ diff --git a/chapters/images/docker-architecture.png b/chapters/images/docker-architecture.png deleted file mode 100644 index 26d8058..0000000 Binary files a/chapters/images/docker-architecture.png and /dev/null differ diff --git a/chapters/images/docker-compose-output.png b/chapters/images/docker-compose-output.png deleted file mode 100644 index 1837bcf..0000000 Binary files a/chapters/images/docker-compose-output.png and /dev/null differ diff --git a/chapters/images/docker-swarm-components.png b/chapters/images/docker-swarm-components.png deleted file mode 100644 index 21b498d..0000000 Binary files a/chapters/images/docker-swarm-components.png and /dev/null differ diff --git a/chapters/images/javaee7-hol-container-linking.png b/chapters/images/javaee7-hol-container-linking.png deleted file mode 100644 index 3bc6e1a..0000000 Binary files a/chapters/images/javaee7-hol-container-linking.png and /dev/null differ diff --git a/chapters/images/javaee7-hol-in-memory-database.png b/chapters/images/javaee7-hol-in-memory-database.png deleted file mode 100644 index d5262f1..0000000 Binary files a/chapters/images/javaee7-hol-in-memory-database.png and /dev/null differ diff --git a/chapters/images/javaee7-hol.png b/chapters/images/javaee7-hol.png deleted file mode 100644 index ebf0f96..0000000 Binary files a/chapters/images/javaee7-hol.png and /dev/null differ diff --git a/chapters/images/javaee7-movieplex7.png b/chapters/images/javaee7-movieplex7.png deleted file mode 100644 index dc3b09f..0000000 Binary files a/chapters/images/javaee7-movieplex7.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-all-containers.png b/chapters/images/jbds-docker-tools-all-containers.png deleted file mode 100644 index 3a7f734..0000000 Binary files a/chapters/images/jbds-docker-tools-all-containers.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-customize-view-option.png b/chapters/images/jbds-docker-tools-customize-view-option.png deleted file mode 100644 index adcfe9e..0000000 Binary files a/chapters/images/jbds-docker-tools-customize-view-option.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-customize-view-wizard.png b/chapters/images/jbds-docker-tools-customize-view-wizard.png deleted file mode 100644 index b4d6f88..0000000 Binary files a/chapters/images/jbds-docker-tools-customize-view-wizard.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-display-log.png b/chapters/images/jbds-docker-tools-display-log.png deleted file mode 100644 index 4feb7e8..0000000 Binary files a/chapters/images/jbds-docker-tools-display-log.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-docker-explorer-view.png b/chapters/images/jbds-docker-tools-docker-explorer-view.png deleted file mode 100644 index d2920e5..0000000 Binary files a/chapters/images/jbds-docker-tools-docker-explorer-view.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-docker-view.png b/chapters/images/jbds-docker-tools-docker-view.png deleted file mode 100644 index 4b81921..0000000 Binary files a/chapters/images/jbds-docker-tools-docker-view.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-nightly-setup.png b/chapters/images/jbds-docker-tools-nightly-setup.png deleted file mode 100644 index 0ad6ac2..0000000 Binary files a/chapters/images/jbds-docker-tools-nightly-setup.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-properties-info.png b/chapters/images/jbds-docker-tools-properties-info.png deleted file mode 100644 index 8985907..0000000 Binary files a/chapters/images/jbds-docker-tools-properties-info.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-properties-inspect.png b/chapters/images/jbds-docker-tools-properties-inspect.png deleted file mode 100644 index acbbf6f..0000000 Binary files a/chapters/images/jbds-docker-tools-properties-inspect.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-run-container-wizard.png b/chapters/images/jbds-docker-tools-run-container-wizard.png deleted file mode 100644 index 5d252c2..0000000 Binary files a/chapters/images/jbds-docker-tools-run-container-wizard.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools-test-connection-output.png b/chapters/images/jbds-docker-tools-test-connection-output.png deleted file mode 100644 index 80de4b9..0000000 Binary files a/chapters/images/jbds-docker-tools-test-connection-output.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools1.png b/chapters/images/jbds-docker-tools1.png deleted file mode 100644 index 414f2eb..0000000 Binary files a/chapters/images/jbds-docker-tools1.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools2.png b/chapters/images/jbds-docker-tools2.png deleted file mode 100644 index 3080bbb..0000000 Binary files a/chapters/images/jbds-docker-tools2.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools3.png b/chapters/images/jbds-docker-tools3.png deleted file mode 100644 index 51998e5..0000000 Binary files a/chapters/images/jbds-docker-tools3.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools4.png b/chapters/images/jbds-docker-tools4.png deleted file mode 100644 index 9391143..0000000 Binary files a/chapters/images/jbds-docker-tools4.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools5.png b/chapters/images/jbds-docker-tools5.png deleted file mode 100644 index d2dba49..0000000 Binary files a/chapters/images/jbds-docker-tools5.png and /dev/null differ diff --git a/chapters/images/jbds-docker-tools6.png b/chapters/images/jbds-docker-tools6.png deleted file mode 100644 index 83ef088..0000000 Binary files a/chapters/images/jbds-docker-tools6.png and /dev/null differ diff --git a/chapters/images/jbds1.png b/chapters/images/jbds1.png deleted file mode 100644 index e3a6323..0000000 Binary files a/chapters/images/jbds1.png and /dev/null differ diff --git a/chapters/images/jbds10.png b/chapters/images/jbds10.png deleted file mode 100644 index 129a36e..0000000 Binary files a/chapters/images/jbds10.png and /dev/null differ diff --git a/chapters/images/jbds11.png b/chapters/images/jbds11.png deleted file mode 100644 index c48c0e3..0000000 Binary files a/chapters/images/jbds11.png and /dev/null differ diff --git a/chapters/images/jbds2.png b/chapters/images/jbds2.png deleted file mode 100644 index 5fe5692..0000000 Binary files a/chapters/images/jbds2.png and /dev/null differ diff --git a/chapters/images/jbds3.png b/chapters/images/jbds3.png deleted file mode 100644 index 8538773..0000000 Binary files a/chapters/images/jbds3.png and /dev/null differ diff --git a/chapters/images/jbds4.png b/chapters/images/jbds4.png deleted file mode 100644 index 55cd5ed..0000000 Binary files a/chapters/images/jbds4.png and /dev/null differ diff --git a/chapters/images/jbds5.png b/chapters/images/jbds5.png deleted file mode 100644 index 71b9012..0000000 Binary files a/chapters/images/jbds5.png and /dev/null differ diff --git a/chapters/images/jbds6.png b/chapters/images/jbds6.png deleted file mode 100644 index f0cc952..0000000 Binary files a/chapters/images/jbds6.png and /dev/null differ diff --git a/chapters/images/jbds7.png b/chapters/images/jbds7.png deleted file mode 100644 index 17c1c41..0000000 Binary files a/chapters/images/jbds7.png and /dev/null differ diff --git a/chapters/images/jbds8.png b/chapters/images/jbds8.png deleted file mode 100644 index 675d7f7..0000000 Binary files a/chapters/images/jbds8.png and /dev/null differ diff --git a/chapters/images/jbds9.png b/chapters/images/jbds9.png deleted file mode 100644 index 02efa97..0000000 Binary files a/chapters/images/jbds9.png and /dev/null differ diff --git a/chapters/images/kubernetes-cluster-vagrant.png b/chapters/images/kubernetes-cluster-vagrant.png deleted file mode 100644 index 1297b95..0000000 Binary files a/chapters/images/kubernetes-cluster-vagrant.png and /dev/null differ diff --git a/chapters/images/kubernetes-key-components.png b/chapters/images/kubernetes-key-components.png deleted file mode 100644 index 4ccab77..0000000 Binary files a/chapters/images/kubernetes-key-components.png and /dev/null differ diff --git a/chapters/images/kubernetes-master-default-output-certificate.png b/chapters/images/kubernetes-master-default-output-certificate.png deleted file mode 100644 index d85f769..0000000 Binary files a/chapters/images/kubernetes-master-default-output-certificate.png and /dev/null differ diff --git a/chapters/images/kubernetes-master-default-output.png b/chapters/images/kubernetes-master-default-output.png deleted file mode 100644 index 92072df..0000000 Binary files a/chapters/images/kubernetes-master-default-output.png and /dev/null differ diff --git a/chapters/images/kubernetes-service.png b/chapters/images/kubernetes-service.png deleted file mode 100644 index 60f7efd..0000000 Binary files a/chapters/images/kubernetes-service.png and /dev/null differ diff --git a/chapters/images/openshiftv3-stack.png b/chapters/images/openshiftv3-stack.png deleted file mode 100644 index f67fcc2..0000000 Binary files a/chapters/images/openshiftv3-stack.png and /dev/null differ diff --git a/chapters/images/openshiftv3-wildfly-mysql-deployment.png b/chapters/images/openshiftv3-wildfly-mysql-deployment.png deleted file mode 100644 index 5d7a392..0000000 Binary files a/chapters/images/openshiftv3-wildfly-mysql-deployment.png and /dev/null differ diff --git a/chapters/images/plain-wildfly0.png b/chapters/images/plain-wildfly0.png deleted file mode 100644 index 58d5484..0000000 Binary files a/chapters/images/plain-wildfly0.png and /dev/null differ diff --git a/chapters/images/plain-wildfly1.png b/chapters/images/plain-wildfly1.png deleted file mode 100644 index 7759697..0000000 Binary files a/chapters/images/plain-wildfly1.png and /dev/null differ diff --git a/chapters/images/ticket-monster_tutorial_architecture.png b/chapters/images/ticket-monster_tutorial_architecture.png deleted file mode 100644 index c3dcd29..0000000 Binary files a/chapters/images/ticket-monster_tutorial_architecture.png and /dev/null differ diff --git a/chapters/images/wildfly-admin-console.png b/chapters/images/wildfly-admin-console.png deleted file mode 100644 index e5c3d68..0000000 Binary files a/chapters/images/wildfly-admin-console.png and /dev/null differ diff --git a/chapters/images/wildfly9-add-deployments.png b/chapters/images/wildfly9-add-deployments.png deleted file mode 100644 index a3661d8..0000000 Binary files a/chapters/images/wildfly9-add-deployments.png and /dev/null differ diff --git a/chapters/images/wildfly9-deployments-tab.png b/chapters/images/wildfly9-deployments-tab.png deleted file mode 100644 index 8eb582f..0000000 Binary files a/chapters/images/wildfly9-deployments-tab.png and /dev/null differ diff --git a/chapters/images/wildfly9-javaee7-simple-sample-deployed.png b/chapters/images/wildfly9-javaee7-simple-sample-deployed.png deleted file mode 100644 index f66d36c..0000000 Binary files a/chapters/images/wildfly9-javaee7-simple-sample-deployed.png and /dev/null differ diff --git a/chapters/images/wildfly9-javaee7-simple-sample-output.png b/chapters/images/wildfly9-javaee7-simple-sample-output.png deleted file mode 100644 index fefe161..0000000 Binary files a/chapters/images/wildfly9-javaee7-simple-sample-output.png and /dev/null differ diff --git a/chapters/images/wildfly_cluster1.png b/chapters/images/wildfly_cluster1.png deleted file mode 100644 index 3307a19..0000000 Binary files a/chapters/images/wildfly_cluster1.png and /dev/null differ diff --git a/chapters/images/wildfly_cluster2.png b/chapters/images/wildfly_cluster2.png deleted file mode 100644 index fbfb28b..0000000 Binary files a/chapters/images/wildfly_cluster2.png and /dev/null differ diff --git a/chapters/images/wildfly_cluster3.png b/chapters/images/wildfly_cluster3.png deleted file mode 100644 index 4012648..0000000 Binary files a/chapters/images/wildfly_cluster3.png and /dev/null differ diff --git a/chapters/images/wildfly_cluster4.png b/chapters/images/wildfly_cluster4.png deleted file mode 100644 index 050750b..0000000 Binary files a/chapters/images/wildfly_cluster4.png and /dev/null differ diff --git a/convert.sh b/convert.sh deleted file mode 100755 index 1db1726..0000000 --- a/convert.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -# Run using: -# -# ./convert.sh -# -# or -# -# ./convert.sh html,pdf -# -# ...where the first argument is a comma-delimited list of formats - -# Program paths -ASCIIDOCTOR=asciidoctor -FOPUB=~/tools/asciidoctor-fopub/fopub -ASCIIDOCTOR_PDF=~/tools/asciidoctor-pdf/bin/asciidoctor-pdf -#FOPUB=~/projects/asciidoctor/fopub/fopub -#ASCIIDOCTOR_PDF=~/projects/asciidoctor/asciidoctor-pdf/bin/asciidoctor-pdf - -# File names -MASTER_ADOC=readme.adoc -MASTER_DOCBOOK=${MASTER_ADOC/.adoc/.xml} - -# Command options -SHARED_OPTIONS='-a numbered -a experimental -a source-highlighter=coderay -a imagesdir=images' - -# Formats -if [ ! -z $1 ]; then - read -a FORMATS <<<$(IFS=','; echo $1) -else - FORMATS=(html -docbook -fopdf) -fi - -for f in ${FORMATS[*]}; do - if [ $f == 'html' ]; then - echo "Converting to HTML ..." - $ASCIIDOCTOR -v $SHARED_OPTIONS $MASTER_ADOC - elif [ $f == 'docbook' ]; then - echo "Converting to DocBook ..." - $ASCIIDOCTOR -b docbook $SHARED_OPTIONS $MASTER_ADOC - elif [ $f == 'fopdf' ]; then - echo "Converting to FO-PDF ..." - $FOPUB $MASTER_DOCBOOK - elif [ $f == 'pdf' ]; then - echo "Converting to PDF ..." - $ASCIIDOCTOR_PDF $SHARED_OPTIONS $MASTER_ADOC - fi -done - -exit 0 diff --git a/docker-orchestration-frameworks.adoc b/docker-orchestration-frameworks.adoc new file mode 100644 index 0000000..b8e9499 --- /dev/null +++ b/docker-orchestration-frameworks.adoc @@ -0,0 +1,30 @@ += Docker vs Kubernetes vs DC/OS vs ECS + +This document compares the four container orchestration frameworks: http://github.com/docker/docker[Docker Engine w/ Swarm Mode], https://github.com/kubernetes/kubernetes[Kubernetes], https://github.com/dcos/dcos[DC/OS], and https://aws.amazon.com/ecs/[ECS]. + + +[width="100%", options="header"] +|================== +| Feature | http://github.com/docker/docker[Docker] | https://github.com/kubernetes/kubernetes[Kubernetes] | https://github.com/dcos/dcos[DC/OS] | https://aws.amazon.com/ecs/[ECS] +| Local Development | https://www.docker.com/community-edition[Docker Community Edition] | https://github.com/kubernetes/minikube[minikube] | https://dcos.io/docs/1.8/administration/installing/local[DC/OS Vagrant] | https://github.com/blox/blox[Blox] +| Multiple clouds | https://docs.docker.com/docker-cloud/overview/[Docker Cloud], https://docs.docker.com/machine/drivers/[Docker Machine Drivers], https://www.docker.com/products/overview[Docker for AWS/Azure] | http://kubernetes.io/docs/getting-started-guides/#turn-key-cloud-solutions[Turn Key Cloud] | https://dcos.io/install/[Mulitple clouds] | AWS +| Service Discovery and Load Balancer | Docker-compse: DNS + +Docker Swarm: (https://docs.docker.com/engine/swarm/services/[Service]) | `Service` | Yes (https://dcos.io/docs/1.8/usage/service-discovery/[multiple]: DNS-based and proxy-based/L4 load balancer) | https://github.com/awslabs/service-discovery-ecs-dns[DNS-based], https://github.com/awslabs/ecs-refarch-service-discovery[ELB-based], https://github.com/awslabs/ecs-refarch-cloudformation[ALB-based] +| Dynamic Scaling | http://blog.couchbase.com/2016/july/docker-services-stack-distributed-application-bundle[Services, Distributed Application Bundle, Stack] | `Replica Set`, `Replication Controller`, `Deployment`, `Horizontal Pod Autoscaling` | Marathon app spec (instance count) and https://dcos.io/docs/1.8/usage/tutorials/autoscaling/[multiple options] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-auto-scaling.html[Service Auto Scaling] +| Exposing a service | Routing mesh | `type=LoadBalancer` in `Deployment` | Multiple (direct placement on public agent or, preferred, via https://dcos.io/docs/1.8/usage/service-discovery/marathon-lb/marathon-lb-basic-tutorial/[Marathon-LB] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html[Classic and Application Load Balancer] +| Run-once job | `docker run` | `Job` | https://docs.mesosphere.com/1.8/usage/jobs/[Jobs] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_run_task.html[Tasks] +| Namespace | `docker-compose -p ` | `Namespace` | via labels in System Marathon | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html#attributes[Custom Attributes] +| Global service| `--mode=global` | `DaemonSet` | Unique Attribute | 'distinctInstance' http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html#constraint-types[Task Placement Constraint] +| Maven | https://github.com/fabric8io/docker-maven-plugin[fabric8-maven-plugin] | https://github.com/fabric8io/docker-maven-plugin[fabric8-maven-plugin] | https://github.com/dcos-labs/dcos-maven-plugin[dcos-maven-plugin] | No +| Volumes | https://docs.docker.com/engine/tutorials/dockervolumes/[Docker Volumes] | http://kubernetes.io/docs/user-guide/persistent-volumes/[Persistent Volumes] | https://dcos.io/docs/1.8/usage/storage/persistent-volume/[local persistent volumes] as well as https://dcos.io/docs/1.8/usage/storage/external-storage/[external persistent volumes] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_data_volumes.html[Using Data Volumes in Tasks] +| Multiple Master | Yes | link:https://github.com/kubernetes/kops[Yes] | Yes | Yes (default) +| Multi-host networking | Yes | Yes | Yes | https://github.com/aws/amazon-ecs-agent/pull/701[Proposed implementation] +| Rolling Update | https://github.com/arun-gupta/docker-scripts/blob/master/rolling-updates.adoc | https://github.com/arun-gupta/kubernetes-java-sample/tree/master/rolling-update | https://github.com/mhausenblas/zdd-lab[ZDD Lab] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/update-service.html[Updating a Service] +| Container distribution strategies | Automatic? | Automatic, but custom schedulers supported. | Automatic | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html[Task Placement Strategies] +| Affinity | Labels | Node (1.2) and Pod (1.4) affinity http://kubernetes.io/docs/user-guide/node-selection/ | https://mesosphere.github.io/marathon/docs/constraints.html[Marathon constraints] and pods (in 1.9) | Via Task Placement Strategies and Constraints +| Constraints | `-c`, `-m` | `Labels` | https://mesosphere.github.io/marathon/docs/constraints.html[Marathon constraints] | http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html[Task Placement Constraints] +| On-premise | Yes | Yes | Yes | No +| Cluster across multiple clouds | Yes | Yes (http://kubernetes.io/docs/admin/multiple-zones/[partly]) | Yes (agents) | No (Can span multiple AZ) +| Commercially supported | https://www.docker.com/enterprise-edition[Docker Enterprise Edition] | Google, Apprenda, Canonical, CoreOS, link:http://cloud-rti.com[Cloud RTI] others? | https://mesosphere.com/product/[Mesosphere Enterprise DC/OS] | https://aws.amazon.com/premiumsupport/[AWS Support] +| Creating Couchbase Cluster | http://blog.couchbase.com/2016/may/couchbase-cluster-docker-swarm-compose-machine[blog] | http://blog.kubernetes.io/2016/08/create-couchbase-cluster-using-kubernetes.html[blog] | http://blog.couchbase.com/2016/november/couchbase-cluster-mesos-dcos[blog] | https://blog.couchbase.com/couchbase-docker-container-amazon-ecs/[blog] (one node) +|================== diff --git a/instructor/.gitignore b/instructor/.gitignore deleted file mode 100644 index 4a5f5f8..0000000 --- a/instructor/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ticket-monster -dockerfiles/ticketmonster-pgsql-wildfly/ticket-monster.war \ No newline at end of file diff --git a/instructor/build-images.sh b/instructor/build-images.sh deleted file mode 100755 index e9bd45d..0000000 --- a/instructor/build-images.sh +++ /dev/null @@ -1 +0,0 @@ -docker build -t "instructor/ticketmonster-pgsql-wildfly" dockerfiles/ticketmonster-pgsql-wildfly/ diff --git a/instructor/docker-compose.yml b/instructor/docker-compose.yml deleted file mode 100644 index 769d7a0..0000000 --- a/instructor/docker-compose.yml +++ /dev/null @@ -1,60 +0,0 @@ -registryv1: - image: registry:0.9.1 - ports: - - "5000:5000" - environment: - - DISABLE_TOKEN_AUTH=true - - SETTINGS_FLAVOR=local - - SEARCH_BACKEND=sqlalchemy - - STORAGE_PATH=/var/lib/registry - volumes: - - /srv/docker/registry_v1:/var/lib/registry - restart: always -httpserver: - build: dockerfiles/lab-httpd-server/ - ports: - - "8082:80" - restart: always -nexus: - image: sonatype/nexus:oss - ports: - - "8081:8081" - volumes_from: - - nexusdata - restart: always -postgresqlgitlab: - image: sameersbn/postgresql:9.4 - environment: - - DB_USER=gitlab - - DB_PASS=password - - DB_NAME=gitlabhq_production - volumes: - - /srv/docker/gitlab/postgresql:/var/lib/postgresql - restart: always -redisgitlab: - image: sameersbn/redis:latest - volumes: - - /srv/docker/gitlab/redis:/var/lib/redis - restart: always -gitlab: - image: sameersbn/gitlab:7.10.4 - links: - - redisgitlab:redisio - - postgresqlgitlab:postgresql - ports: - - "10080:80" - - "10022:22" - environment: - - GITLAB_HOST=localhost - - GITLAB_PORT=10080 - - GITLAB_SSH_PORT=10022 - - GITLAB_ROOT_PASSWORD=dockeradmin - - GITLAB_USERNAME_CHANGE=false - - GITLAB_CREATE_GROUP=false - - GITLAB_PROJECTS_ISSUES=false - - GITLAB_PROJECTS_MERGE_REQUESTS=false - - GITLAB_PROJECTS_WIKI=false - - GITLAB_BACKUPS=disable - volumes: - - /srv/docker/gitlab/gitlab:/home/git/data - restart: always diff --git a/instructor/dockerfiles/lab-httpd-server/Dockerfile b/instructor/dockerfiles/lab-httpd-server/Dockerfile deleted file mode 100644 index efdbc48..0000000 --- a/instructor/dockerfiles/lab-httpd-server/Dockerfile +++ /dev/null @@ -1,98 +0,0 @@ -FROM fedora:22 - -MAINTAINER Rafael Benevides - -#Install wget and Apache HTTPD -RUN dnf -y update && dnf -y install httpd && dnf clean all -ADD index.html /var/www/html/ - -RUN mkdir -p /var/www/html/downloads - -#Change Workdir to apache dir -WORKDIR /var/www/html/downloads - -#Place JBDS inside the image -ADD downloads/jboss-devstudio-9.0.0.Beta2-v20150609-1026-B3346-installer-standalone.jar /var/www/html/downloads/ - -#Setup permission for JBDS -RUN chmod 644 /var/www/html/downloads/jboss-devstudio-9.0.0.Beta2-v20150609-1026-B3346-installer-standalone.jar - -#Get WildFly 9.0 -RUN curl -L http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.zip -o wildfly-8.2.0.Final.zip - -#Get Boot2docker 1.6.2 -RUN curl -L https://github.com/boot2docker/boot2docker/releases/download/v1.7.0/boot2docker.iso -o boot2docker.iso - -RUN mkdir -p /var/www/html/downloads/virtualbox -WORKDIR /var/www/html/downloads - -#Get VirtualBox for MAC -RUN curl -L http://download.virtualbox.org/virtualbox/4.3.26/VirtualBox-4.3.26-98988-OSX.dmg -o VirtualBox-4.3.26-98988-OSX.dmg - -#Get VirtualBox for Windows -RUN curl -L http://download.virtualbox.org/virtualbox/4.3.26/VirtualBox-4.3.26-98988-Win.exe -o VirtualBox-4.3.26-98988-Win.exe - -#Get VirtualBox for Linux (All Distros) -RUN curl -L http://download.virtualbox.org/virtualbox/4.3.26/VirtualBox-4.3.26-98988-Linux_amd64.run -o VirtualBox-4.3.26-98988-Linux_amd64.run - -WORKDIR /var/www/html/downloads - -#Get Git for Windows -RUN curl -L https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe -o Git-1.9.5-preview20150319.exe - -RUN mkdir -p /var/www/html/downloads/docker -WORKDIR /var/www/html/downloads/docker - -#Get Docker Machine Windows -RUN curl -L https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_windows-amd64.exe -o docker-machine.exe - -#Get Docker Machine MacOS -RUN curl -L https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_darwin-amd64 -o docker-machine_darwin-amd64 - -#Get Docker Machine Linux -RUN curl -L https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_linux-amd64 -o docker-machine_linux-amd64 - -#Get Docker Client Mac OS -RUN curl -L https://get.docker.com/builds/Darwin/x86_64/docker-latest -o docker-latest-mac - -#Get Docker Client Linux -RUN curl -L https://get.docker.com/builds/Linux/x86_64/docker-latest -o docker-latest-linux - -#Get Docker Client Windows -RUN curl -L http://test.docker.com.s3.amazonaws.com/builds/Windows/x86_64/docker-1.7.0.exe -o docker-1.7.0.exe - -WORKDIR /var/www/html/downloads - -#Get Maven binaries -RUN curl -L http://apache.mirrors.tds.net/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.zip -o apache-maven-3.3.3-bin.zip - -RUN mkdir -p /var/www/html/downloads/vagrant -WORKDIR /var/www/html/downloads/vagrant - -#Get Vagrant MacOS -RUN curl -L https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2.dmg -o vagrant_1.7.2.dmg - -#Get Vagrant Windows -RUN curl -L https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2.msi -o vagrant_1.7.2.msi - -#Get Vagrant Debian 64-bit -RUN curl -L https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_x86_64.deb -o vagrant_1.7.2_x86_64.deb - -#Get Vagrant Linux 64-bit -RUN curl -L https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_x86_64.rpm -o vagrant_1.7.2_x86_64.rpm - -#Get Kubernetes -RUN curl -L https://github.com/GoogleCloudPlatform/kubernetes/releases/tag/v0.21.0 -o kubernetes.tar.gz - -#Add other files to downloads -ADD downloads/lab-settings.xml /var/www/html/downloads/ - -EXPOSE 80 - -# Simple startup script to avoid some issues observed with container restart -ADD run-apache.sh /run-apache.sh -RUN chmod -v +x /run-apache.sh - -#Run the default apache command -CMD ["/run-apache.sh"] - diff --git a/instructor/dockerfiles/lab-httpd-server/downloads/.gitignore b/instructor/dockerfiles/lab-httpd-server/downloads/.gitignore deleted file mode 100644 index c27dc41..0000000 --- a/instructor/dockerfiles/lab-httpd-server/downloads/.gitignore +++ /dev/null @@ -1 +0,0 @@ -jboss-devstudio-8.1.0.GA-installer-standalone.jar \ No newline at end of file diff --git a/instructor/dockerfiles/lab-httpd-server/downloads/lab-settings.xml b/instructor/dockerfiles/lab-httpd-server/downloads/lab-settings.xml deleted file mode 100644 index a78e2c7..0000000 --- a/instructor/dockerfiles/lab-httpd-server/downloads/lab-settings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - instructor-repository - - - instructor-nexus-repository - http://classroom.example.com:8081/content/groups/public/ - - true - - - false - - - - - - instructor-plugin-repository - http://classroom.example.com:8081/content/groups/public/ - - true - - - false - - - - - - - - - - instructor-repository - - - diff --git a/instructor/dockerfiles/lab-httpd-server/index.html b/instructor/dockerfiles/lab-httpd-server/index.html deleted file mode 100644 index 3f96848..0000000 --- a/instructor/dockerfiles/lab-httpd-server/index.html +++ /dev/null @@ -1,4398 +0,0 @@ - - - - - - - - -Docker and Kubernetes for Java EE Developers - - - - - - -
-
-
-
-
Table of Contents
- -
-
-
-
-

1. Preface

-
-
-

Containers are enabling developers to package their applications (and underlying dependencies) in new ways that are portable and work consistently everywhere? On your machine, in production, in your data center, and in the cloud. And Docker has become the de facto standard for those portable containers in the cloud.

-
-
-

Docker is the developer-friendly Linux container technology that enables creation of your stack: OS, JVM, app server, app, and all your custom configuration. So with all it offers, how comfortable are you and your team taking Docker from development to production? Are you hearing developers say, “But it works on my machine!” when code breaks in production?

-
-
-

This lab offers developers an intro-level, hands-on session with Docker, from installation, to exploring Docker Hub, to crafting their own images, to adding Java apps and running custom containers. It will also explain how to use Swarm to orchesorchestrate these containers together. This is a BYOL (bring your own laptop) session, so bring your Windows, OSX, or Linux laptop and be ready to dig into a tool that promises to be at the forefront of our industry for some time to come.

-
-
- - - - - -
-
Note
-
-Latest content of this lab is always at https://github.com/javaee-samples/docker-java -
-
-
-
-
-

2. Setup Environments

-
-
-

This section describes the relevant steps for both attendees and instructors to setup the environments. Please follow the parts, that are appropriate for you.

-
-
-

2.1. Instructor

-
-

The instructor setup is designed to make the lab most reliable even with bad Internet connections. Most, if not all, of the software can be directly downloaded from the instructor’s machine. The machine is setup as Docker Host and also runs a Docker Registry and Nexus container.

-
-
-

Follow all the instructor setup instructions at least a day before the lab. Make sure there is a decent Internet connection available.

-
-
-
-

2.2. Attendees (From Instructor’s Machine)

-
-

This lab is designed for a BYOL (Brying Your Own Laptop) style hands-on-lab. This section provide instructions to setup an attendee environment from an instructor’s machine.

-
- -
-

2.2.1. Hardware

-
-
    -
  1. -

    CPU

    -
    -
      -
    1. -

      Mac: X64 (i5 or superior)

      -
    2. -
    3. -

      Linux / Windows: x64 (i5 and comparable)

      -
    4. -
    -
    -
  2. -
  3. -

    Memory

    -
    -
      -
    1. -

      At least 4GB, preferred 8 GB

      -
    2. -
    -
    -
  4. -
-
-
-
-

2.2.2. Software

-
-
    -
  1. -

    Operating System

    -
    -
      -
    1. -

      Mac OS X (10.8 or later), Windows 7 (SP1), Fedora (21 or later)

      -
    2. -
    -
    -
  2. -
  3. -

    Java: Oracle JDK 8u45

    -
  4. -
  5. -

    Webbrowser

    -
    -
      -
    1. -

      Chrome

      -
    2. -
    3. -

      Firefox

      -
    4. -
    -
    -
  6. -
-
-
-
-

2.2.3. A Word About Licenses

-
-

This tutorial only uses software which is open source or at least free to use in development and/or education. Please refer to the individual products/tools used in this tutorial.

-
-
-
-

2.2.4. Configure Instructor Host

-
-

All downloads and relevant infrastructure is setup on instructor’s machine. Configure the IP address of instructor’s machine into the resolver configuration of your operating system.

-
-
-

Edit the /etc/resolv.conf (Mac OS / Linux)

-
-
-
-
nameserver  <INSTRUCTOR IP>
-
-
-
-

On Windows, configure Domain Suffixes or DNS Suffixes as explained at http://www.pc-freak.net/blog/configure-equivalent-linux-etcresolvconf-search-domaincom-ms-windows-dns-suffixes/.

-
-
-
-

2.2.5. Git Client

- - -
-
-

2.2.6. Maven

-
-
    -
  1. -

    Download Apache Maven from http://classroom.example.com:8082/downloads/apache-maven-3.3.3-bin.zip

    -
  2. -
  3. -

    Unzip to a folder of your choice and add the folder to your PATH environment variable.

    -
  4. -
-
-
-
-

2.2.7. VirtualBox

-
-

Docker currently runs natively on Linux, but you can use VirtualBox to run Docker in a virtual machine on your box, and get the best of both worlds. This is why Virtualbox is a requirement to have on your machine. Get the latest downloads from the instructur machine:

-
-
-

Downloads are available from Mac, Linux, Windows.

-
-
- - - - - -
-
Warning
-
-
-

Linux Users

-
-
-
    -
  1. -

    Have your kernel updated

    -
  2. -
  3. -

    Users should have the GNU compiler, build and header files for your current Linux kernel

    -
  4. -
  5. -

    Create a /usr/src/linux link to the current kernel source

    -
  6. -
-
-
-
-
-
-

2.2.8. Vagrant

-
-
    -
  1. -

    Download Vagrant for Mac, Windows, Linux or Debian and install.

    -
  2. -
-
-
-
-

2.2.9. Docker Machine

-
-

Download your binary from http://classroom.example.com:8082/downloads/

-
-
-
-
# MacOS
-curl -L  http://classroom.example.com:8082/downloads/docker-machine_darwin-amd64 > /usr/local/bin/docker-machine
-chmod +x /usr/local/bin/docker-machine
-
-# Linux
-curl -L  http://classroom.example.com:8082/downloads/docker-machine_linux-amd64 > /usr/local/bin/docker-machine
-chmod +x /usr/local/bin/docker-machine
-
-#Windows
-curl http://classroom.example.com:8082/downloads/docker-machine_windows-amd64.exe
-
-
-
-

On Windows copy the script into C:\docker directory and rename to: docker-machine.exe. Add C:\docker to your PATH variable.

-
-
-
-

2.2.10. Docker Client

-
-

Download your binary from http://classroom.example.com:8082/downloads/

-
-
-
-
# MacOS
-curl -L  http://classroom.example.com:8082/downloads/docker-latest-mac > /usr/local/bin/docker
-chmod +x /usr/local/bin/docker
-
-# Linux (other distros)
-curl -L  http://classroom.example.com:8082/downloads/docker-latest-linux > /usr/local/bin/docker
-chmod +x /usr/local/bin/docker
-
-#Windows
-curl http://classroom.example.com:8082/docker-1.7.0.exe
-
-
-
-

On Windows rename the file to C:\docker\docker.exe.

-
-
-
-

2.2.11. Create Lab Docker Host

-
-
    -
  1. -

    Create the Docker Host to be used in the lab:

    -
    -
    -
    docker-machine create --driver=virtualbox --engine-opt dns=<INSTRUCTOR IP> --virtualbox-boot2docker-url=http://classroom.example.com:8082/downloads/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 lab
    -eval "$(docker-machine env lab)"
    -
    -
    -
    -

    Substitute <INSTRUCTOR_IP> with the IP address of the instructor’s machine.

    -
    -
  2. -
  3. -

    To make it easier to access the containers, we add an entry into the host mapping table of your operating system. Add a host entry for this Docker Host running on your machine. Find out the IP address of your machine:

    -
    -
    -
    docker-machine ip lab
    -
    -
    -
    -

    Edit /etc/hosts (Mac OS or Linux) or C:\Windows\System32\drivers\etc\hosts (Windows) and add:

    -
    -
    -
    -
    <OUTPUT OF DOCKER MACHINE COMMAND>  dockerhost
    -
    -
    -
  4. -
-
-
-
-

2.2.12. Kubernetes

-
-
    -
  1. -

    Download Kubernetes (0.19.3) from http://classroom.example.com:8082/downloads/kubernetes.tar.gz

    -
  2. -
  3. -

    Install it by clicking on the archive.

    -
  4. -
-
-
-
-

2.2.13. WildFly

-
-
    -
  1. -

    Download WildFly 8.2 from http://classroom.example.com:8082/downloads/wildfly-8.2.0.Final.zip

    -
  2. -
  3. -

    Install it by clicking on the archive.

    -
  4. -
-
-
-
-

2.2.14. JBoss Developer Studio 9 - Beta 2

-
-

To install JBoss Developer Studio stand-alone, complete the following steps:

-
-
-
    -
  1. -

    Download http://classroom.example.com:8082/downloads/jboss-devstudio-9.0.0.Beta2-v20150609-1026-B3346-installer-standalone.jar

    -
  2. -
  3. -

    Start the installer as:

    -
    -
    -
    java -jar jboss-devstudio-9.0.0.Beta2-v20150609-1026-B3346-installer-standalone.jar
    -
    -
    -
    -

    Follow the on-screen instructions to complete the installation process.

    -
    -
  4. -
-
-
-
-
-

2.3. Attendees (From Internet)

-
-
    -
  1. -

    Chrome or Firefox

    -
  2. -
  3. -

    Oracle JDK 8 u45

    -
  4. -
  5. -

    Git client

    -
  6. -
  7. -

    Maven 3.3.3

    -
  8. -
  9. -

    Latest Virtual Box

    -
  10. -
  11. -

    Vagrant

    -
  12. -
  13. -

    Docker

    -
    -
      -
    1. -

      Docker Machine

      -
    2. -
    3. -

      Docker Client

      -
      -
        -
      1. -

        Mac: curl https://get.docker.com/builds/Darwin/x86_64/docker-latest > /usr/local/bin/docker

        -
      2. -
      3. -

        Windows: http://test.docker.com.s3.amazonaws.com/builds/Windows/x86_64/docker-1.6.0.exe

        -
      4. -
      5. -

        Linux: apt-get install docker.io

        -
      6. -
      -
      -
    4. -
    -
    -
  14. -
  15. -

    Kubernetes 0.18.1

    -
  16. -
  17. -

    JBoss

    - -
  18. -
-
-
-
-
-
-

3. Docker Basics

-
-
-
-Docker is a platform for developers and sysadmins to develop, ship, and run applications. Docker lets you quickly assemble applications from components and eliminates the friction that can come when shipping code. Docker lets you get your code tested and deployed into production as fast as possible. -
-
-— docs.docker.com/ -
-
-
-

Docker simplifies software delivery by making it easy to build and share images that contain your application’s entire environment, or application operating system.

-
-
-

What does it mean by an application operating system ?

-
-
-

Your application typically require a specific version of operating system, application server, JDK, database server, may require to tune the configuration files, and similarly multiple other dependencies. The application may need binding to specific ports and certain amount of memory. The components and configuration together required to run your application is what is referred to as application operating system.

-
-
-

You can certainly provide an installation script that will download and install these components. Docker simplifies this process by allowing to create an image that contains your application and infrastructure together, managed as one component. These images are then used to create Docker containers which run on the container virtualization platform, provided by Docker.

-
-
-

What can a Java Developer use Docker for?

-
-
-
    -
  1. -

    Faster delivery of your applications: Docker helps you with the development lifecycle. -Docker allows you to develop on local containers that contain your applications -and services. It can then integrate into a continuous integration and -deployment workflow.

    -
    -

    For example, you write code locally and share the development stack -via Docker with colleagues. When everybody is ready, you push the -code and the stack you all are developing onto a test environment -and execute any required tests.

    -
    -
    -

    From the testing environment, you can then push the Docker images -into production and deploy your code.

    -
    -
  2. -
  3. -

    Deploying and scaling more easily: Docker’s container-based platform allows for portable workloads. Docker containers can run on a developer’s local host, on physical -or virtual machines in a data center, or in the Cloud.

    -
    -

    Docker’s portability and lightweight nature also make dynamically managing workloads easy. You can use Docker to quickly scale up or tear down applications and services. Docker is so fast, that scaling can be near real time.

    -
    -
  4. -
-
-
-

How is it different from VM?

-
-
-

Docker is an open source container virtualization platform.

-
-
-

Docker has three main components:

-
-
-
    -
  1. -

    Images are build component of Docker and a read-only template of application operating system.

    -
  2. -
  3. -

    Containers are run component of Docker, and created from, images.Containers can be run, started, stopped, moved, and deleted.

    -
  4. -
  5. -

    Images are stored, shared, and managed in a registry, the distribution component of Docker. The publically available registry is known as Docker Hub.

    -
  6. -
-
-
-

In order for these three components to work together, there is Docker Daemon that runs on a host machine and does the heavy lifting of building, running, and distributing Docker containers. In addition, there is Client that is a Docker binary which accepts commands from the user and communicates back and forth with the daemon.

-
-
-
-docker architecture -
-
Figure 1. Docker architecture
-
-
-

Client communicates with Daemon, either co-located on the same host, or on a different host. It requests the Daemon to pull an image from the repository using pull command. The Daemon then downloads the image from Docker Hub, or whatever registry is configured. Multiple images can be downloaded from the registry and installed on Daemon host. Images are run using run command to create containers on demand.

-
-
-

How does a Docker Image work?

-
-
-

We’ve already seen that Docker images are read-only templates from which Docker containers are launched. Each image consists of a series of layers. Docker makes use of union file systems to combine these layers into a single image. Union file systems allow files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system.

-
-
-

One of the reasons Docker is so lightweight is because of these layers. When you change a Docker image—for example, update an application to a new version— a new layer gets built. Thus, rather than replacing the whole image or entirely rebuilding, as you may do with a virtual machine, only that layer is added or updated. Now you don’t need to distribute a whole new image, just the update, making distributing Docker images faster and simpler.

-
-
-

Every image starts from a base image, for example ubuntu, a base Ubuntu image, or fedora, a base Fedora image. You can also use images of your own as the basis for a new image, for example if you have a base Apache image you could use this as the base of all your web application images.

-
-
- - - - - -
-
Note
-
-By default, Docker obtains these base images from Docker Hub. -
-
-
-

Docker images are then built from these base images using a simple, descriptive set of steps we call instructions. Each instruction creates a new layer in our image. Instructions include actions like:

-
-
-
    -
  1. -

    Run a command.

    -
  2. -
  3. -

    Add a file or directory.

    -
  4. -
  5. -

    Create an environment variable.

    -
  6. -
  7. -

    What process to run when launching a container from this image.

    -
  8. -
-
-
-

These instructions are stored in a file called a Dockerfile. Docker reads this Dockerfile when you request a build of an image, executes the instructions, and returns a final image.

-
-
-

How does a Container work?

-
-
-

A container consists of an operating system, user-added files, and meta-data. As we’ve seen, each container is built from an image. That image tells Docker what the container holds, what process to run when the container is launched, and a variety of other configuration data. The Docker image is read-only. When Docker runs a container from an image, it adds a read-write layer on top of the image (using a union file system as we saw earlier) in which your application can then run.

-
-
-

3.1. Docker Machine

-
-

Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.

-
-
-

Once your Docker host has been created, it then has a number of commands for managing them:

-
-
-
    -
  1. -

    Starting, stopping, restarting

    -
  2. -
  3. -

    Upgrading Docker

    -
  4. -
  5. -

    Configuring the Docker client to talk to your host

    -
  6. -
-
-
-

You used Docker Machine already during the attendee setup. We won’t need it too much further on. But if you need to create hosts, it’s a very handy tool to know about. From now on we’re mostly going to use the docker client.

-
-
-

Find out more about the details at the Official Docker Machine Website

-
-
-

Check if docker machine is working using the following command:

-
-
-
-
docker-machine -v
-
-
-
-

It shows the following output:

-
-
-
-
docker-machine version 0.3.0-rc3 (a5fd8cf)
-
-
-
-
-

3.2. Docker Client

-
-

The client communicates with the demon process on your host and let’s you work with images and containers.

-
-
-

Check if your client is working using the following command:

-
-
-
-
docker -v
-
-
-
-

It shows the following output:

-
-
-
-
Docker version 1.6.2, build 7c8fca2
-
-
-
-

The most important options you’ll be using frequently are:

-
-
-
    -
  1. -

    run - runs a container

    -
  2. -
  3. -

    ps- lists containers

    -
  4. -
  5. -

    stop - stops a container

    -
  6. -
-
-
-

Get a full list of available commands with

-
-
-
-
docker
-
-
-
-
-

3.3. Verify Docker Configuration

-
-

Check if your Docker Host is running:

-
-
-
-
docker-machine ls
-
-
-
-

You should see the output similar to:

-
-
-
-
NAME        ACTIVE   DRIVER       STATE     URL                         SWARM
-lab                  virtualbox   Running   tcp://192.168.99.101:2376
-
-
-
-

If the machine state is stopped, start it with:

-
-
-
-
docker-machine start lab
-
-
-
-

After it is started you can find out IP address of your host with:

-
-
-
-
docker-machine ip lab
-
-
-
-

We already did this during the setup document, remember? So, this is a good chance to check, if you already added this IP to your hosts file.

-
-
-

Type:

-
-
-
-
ping dockerhost
-
-
-
-

and see if this resolves to the IP address that the docker-machine command printed out. You should see an output as:

-
-
-
-
> ping dockerhost
-PING dockerhost (192.168.99.101): 56 data bytes
-64 bytes from 192.168.99.101: icmp_seq=0 ttl=64 time=0.394 ms
-64 bytes from 192.168.99.101: icmp_seq=1 ttl=64 time=0.387 ms
-
-
-
-

If it does, you’re ready to start over with the lab. If it does not, make sure you’ve followed the steps to configure your host.

-
-
-
-
-
-

4. Run Container

-
-
-

The first step in running any application on Docker is to run a container from an image. There are plenty of images available from the official Docker registry (aka Docker Hub). To run any of them, you just have to ask the Docker Client to run it. The client will check if the image already exists on Docker Host. If it exists then it’ll run it, otherwise the host will download the image and then run it.

-
-
-

4.1. Pull Image

-
-

Let’s first check, if there are any images already available:

-
-
-
-
docker images
-
-
-
-

At first, this list is empty. Now, let’s get a plain jboss/wildfly image from the instructor’s registry:

-
-
-
-
docker pull classroom.example.com:5000/wildfly
-
-
-
-

By default, docker images are retrieved from Docker Hub. This lab is pre-congfigured to run such that everything can be pulled from instructor’s machine.

-
-
-

You can see, that Docker is downloading the image with it’s different layers.

-
-
- - - - - -
-
Note
-
-
-

In a traditional Linux boot, the Kernel first mounts the root File System as read-only, checks its integrity, and then switches the whole rootfs volume to read-write mode. -When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. Consider each one of these file systems as a layer.

-
-
-

At first, the top read-write layer has nothing in it, but any time a process creates a file, this happens in the top layer. And if something needs to update an existing file in a lower layer, then the file gets copied to the upper layer and changes go into the copy. The version of the file on the lower layer cannot be seen by the applications anymore, but it is there, unchanged.

-
-
-

We call the union of the read-write layer and all the read-only layers a union file system.

-
-
-
-plain wildfly0 -
-
Figure 2. Docker Layers
-
-
-
-
-

In our particular case, the jboss/wildfly image extends the jboss/base-jdk:7 image which adds the OpenJDK distribution on top of the jboss/base image. -The base image is used for all JBoss community images. It provides a base layer that includes:

-
-
-
    -
  1. -

    A jboss user (uid/gid 1000) with home directory set to /opt/jboss

    -
  2. -
  3. -

    A few tools that may be useful when extending the image or installing software, like unzip.

    -
  4. -
-
-
-

The ``jboss/base-jdk:7'' image adds:

-
-
-
    -
  1. -

    Latest OpenJDK distribution

    -
  2. -
  3. -

    Adds a JAVA_HOME environment variable

    -
  4. -
-
-
-

When the download is done, you can list the images again and will see the following:

-
-
-
-
docker images
-
-REPOSITORY              TAG     IMAGE ID       CREATED       VIRTUAL SIZE
-classroom.example.com:5000/wildfly  latest  2ac466861ca1   10 weeks ago  951.3 MB
-
-
-
-
-

4.2. Run Container

-
-

4.2.1. Interactive Container

-
-

Run WildFly container in an interactive mode.

-
-
-
-
docker run -it classroom.example.com:5000/wildfly
-
-
-
-

This will show the output as:

-
-
-
-
> docker run -it classroom.example.com:5000/wildfly
-=========================================================================
-
-  JBoss Bootstrap Environment
-
-  JBOSS_HOME: /opt/jboss/wildfly
-
-  JAVA: /usr/lib/jvm/java/bin/java
-
-  JAVA_OPTS:  -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
-
-=========================================================================
-
-17:58:58,353 INFO  [org.jboss.modules] (main) JBoss Modules version 1.3.3.Final
-17:58:58,891 INFO  [org.jboss.msc] (main) JBoss MSC version 1.2.2.Final
-17:58:59,056 INFO  [org.jboss.as] (MSC service thread 1-2) JBAS015899: WildFly 8.2.0.Final "Tweek" starting
-
-. . .
-
-17:59:03,211 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
-17:59:03,212 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
-17:59:03,213 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 5310ms - Started 184 of 234 services (82 services are lazy, passive or on-demand)
-
-
-
-

This shows that the server started correctly, congratulations!

-
-
-

By default, Docker runs in the foreground. -i allows to interact with the STDIN and -t attach a TTY to the process. Switches can be combined together and used as -it.

-
-
-

Hit Ctrl+C to stop the container.

-
-
-
-

4.2.2. Detached Container

-
-

Restart the container in detached mode:

-
-
-
-
> docker run -d classroom.example.com:5000/wildfly
-972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
-
-
-
-

-d runs the container in detached mode.

-
-
-

The output is the unique id assigned to the container. Check the logs as:

-
-
-
-
> docker logs 972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
-=========================================================================
-
-  JBoss Bootstrap Environment
-
-  JBOSS_HOME: /opt/jboss/wildfly
-
-. . .
-
-
-
-

We can check it by issuing the docker ps command which retrieves the images process which are running and the ports engaged by the process:

-
-
-
-
> docker ps
-CONTAINER ID        IMAGE                                 COMMAND                CREATED             STATUS              PORTS                    NAMES
-0bc123a8ece0        classroom.example.com:5000/wildfly:latest    "/opt/jboss/wildfly/   4 seconds ago       Up 4 seconds        8080/tcp                 tender_wozniak
-
-
-
-

Also try docker ps -a to see all the containers on this machine.

-
-
-
-
-

4.3. Run Container with Default Port

-
-

Startup log of the server shows that the server is located in the /opt/jboss/wildfly. It also shows that the public interfaces are bound to the 0.0.0.0 address while the admin interfaces are bound just to localhost. This information will be useful to learn how to customize the server.

-
-
-

docker-machine ip <machine-name> gives us the Docker Host IP address and this was already added to the hosts file. So, we can give it another try by accessing: http://dockerhost:8080. However, this will not work either.

-
-
-

If you want containers to accept incoming connections, you will need to provide special options when invoking docker run. The container, we just started, can’t be accessed by our browser. We need to stop it again and restart with different options.

-
-
-
-
docker stop 0bc123a8ece0
-
-
-
-

Restart the container as:

-
-
-
-
> docker ps
-CONTAINER ID        IMAGE                                 COMMAND                CREATED             STATUS              PORTS                     NAMES
-4545ced66242        classroom.example.com:5000/wildfly:latest    "/opt/jboss/wildfly/   3 seconds ago       Up 3 seconds        0.0.0.0:32768->8080/tcp   suspicious_wozniak
-
-
-
-

-P flag map any network ports inside the image it to a random high port from the range 49153 to 65535 on Docker host.

-
-
-

The port mapping is shown in the PORTS column. Access the WildFly server at http://dockerhost:32768:8080. Make sure to use the correct port number as shown in your case.

-
-
-
-

4.4. Run Container with Specified Port

-
-

Lets stop the previously running container as:

-
-
-
-
docker stop 4545ced66242
-
-
-
-

Restart the container as:

-
-
-
-
docker run -it -p 8080:8080 classroom.example.com:5000/wildfly
-
-
-
-

The format is -p hostPort:containerPort. This option maps container ports to host ports and allows other containers on our host to access them.

-
-
- - - - - -
-
Note
-
-
Docker Port Mapping
-
-

Port exposure and mapping are the keys to successful work with Docker. -See more about networking on the Docker website Advanced Networking

-
-
-
-
-

Now we’re ready to test http://dockerhost:8080 again. This works with the exposed port, as expected.

-
-
-
-plain wildfly1 -
-
Figure 3. Welcome WildFly
-
-
-
-

4.5. Enabling WildFly Administration

-
-

Default WildFly image exposes only port 8080 and thus is not available for administration using either the CLI or Admin Console.

-
-
-

4.5.1. Default Port Mapping

-
-

The following command will override the default command in Docker file, explicitly starting WildFly, and binding application and management port to all network interfaces.

-
-
-
-
docker run -P -d classroom.example.com:5000/wildfly /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
-
-
-
-

Accessing WildFly Administration Console require a user in administration realm. A pre-created image, with appropriate username/password credentials, is used to start WildFly as:

-
-
-
-
docker run -P -d classroom.example.com:5000/wildfly-management
-
-
-
-

-P flag map any network ports inside the image it to a random high port from the range 49153 to 65535 on Docker host.

-
-
-

Look at the exposed ports as:

-
-
-
-
 docker ps
-CONTAINER ID        IMAGE                                           COMMAND                CREATED             STATUS              PORTS                                              NAMES
-6f610b310a46        classroom.example.com:5000/wildfly-management:latest   "/bin/sh -c '/opt/jb   6 seconds ago       Up 6 seconds        0.0.0.0:32769->8080/tcp, 0.0.0.0:32770->9990/tcp   determined_darwin
-
-
-
-

Look for the host port that is mapped in the container, 32770 in this case. Access the admin console at http://dockerhost:32770.

-
-
-

The username/password credentials are:

-
- ---- - - - - - - - - - - - - - - - - -
FieldValue

Username

admin

Password

docker#admin

-
-
Additional Ways To Find Port Mapping
-
-

The exact mapped port can also be found as:

-
-
-
    -
  1. -

    Using docker inspect:

    -
    -
    -
    docker inspect --format='{{(index (index .NetworkSettings.Ports "9990/tcp") 0).HostPort}}' 6f610b310a46
    -
    -
    -
  2. -
  3. -

    Using docker port:

    -
    -
    -
    docker port 6f610b310a46
    -
    -
    -
    -

    to see the output as:

    -
    -
    -
    -
    0.0.0.0:32769->8080/tcp
    -0.0.0.0:32770->9990/tcp
    -
    -
    -
  4. -
-
-
-
-
-

4.5.2. Fixed Port Mapping

-
-

This management image can also be started with a pre-defined port mapping as:

-
-
-
-
docker run -p 8080:8080 -p 9990:9990 -d classroom.example.com:5000/wildfly-management
-
-
-
-

In this case, Docker port mapping will be shown as:

-
-
-
-
8080/tcp -> 0.0.0.0:8080
-9990/tcp -> 0.0.0.0:9990
-
-
-
-
-
-

4.6. Stop and Remove Container

-
-

4.6.1. Stop Container

-
-
    -
  1. -

    Stop a specific container:

    -
    -
    -
    docker stop 0bc123a8ece0
    -
    -
    -
  2. -
  3. -

    Stop all the running containers

    -
    -
    -
    docker rm $(docker stop $(docker ps -q))
    -
    -
    -
  4. -
  5. -

    Stop only the exited containers

    -
    -
    -
    docker ps -a -f "exited=-1"
    -
    -
    -
  6. -
-
-
-
-

4.6.2. Remove Container

-
-
    -
  1. -

    Remove a specific container:

    -
    -
    -
    docker rm 0bc123a8ece0
    -
    -
    -
  2. -
  3. -

    Containers meeting a regular expression

    -
    -
    -
    docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm
    -
    -
    -
  4. -
  5. -

    All running containers, without any criteria

    -
    -
    -
    docker rm $(docker ps -aq)
    -
    -
    -
  6. -
-
-
-
-
-
-
-

5. Deploy Java EE 7 Application (Pre-Built WAR)

-
-
-

Java EE 7 Hands-on Lab has been delivered all around the world and is a pretty standard application that shows design patterns and anti-patterns for a typical Java EE 7 application.

-
-
-
-javaee7 hol -
-
Figure 4. Java EE 7 Application Architecture
-
-
-

Pull the Docker image that contains WildFly and pre-built Java EE 7 application WAR file as shown:

-
-
-
-
docker pull classroom.example.com:5000/javaee7-hol
-
-
-
-

The javaee7-hol Dockerfile is based on jboss/wildfly and adds the movieplex7 application as war file.

-
-
-

Run it as:

-
-
-
-
docker run -it -p 8080:8080 classroom.example.com:5000/javaee7-hol
-
-
-
-

See the application in action at http://dockerhost:8080/movieplex7/.

-
-
-

This uses an in-memory database with WildFly application server as shown in the image:

-
-
-
-javaee7 hol in memory database -
-
Figure 5. In-memory Database
-
-
-

Only two changes are required to the standard jboss/wildfly image:

-
-
-
    -
  1. -

    Start WildFly in full platform:

    -
    -
    -
    CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]
    -
    -
    -
  2. -
  3. -

    WAR file is copied to standalone/deployments directory as:

    -
    -
    -
    RUN curl -L https://github.com/javaee-samples/javaee7-hol/blob/jrebel/solution/movieplex7-1.0-SNAPSHOT.war?raw=true -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war
    -
    -
    -
  4. -
-
-
-
-
-

6. Deploy Java EE 7 Application (Container Linking)

-
-
-

Deploy Java EE 7 Application (Pre-Built WAR) explained how to use an in-memory database with the application server. This gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost after the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server.

-
-
-
-javaee7 hol container linking -
-
Figure 6. Two Containers On Same Docker Host
-
-
-

This section will show how Docker Container Linking can be used to connect to a service running inside a Docker container via a network port.

-
-
-
    -
  1. -

    Start MySQL server as:

    -
    -
    -
    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
    -
    -
    -
    -

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

    -
    -
  2. -
  3. -

    Start WildFly and deploy Java EE 7 application as:

    -
    -
    -
    docker run -it --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
    -
    -
    -
    -

    --link takes two parameters - first is name of the container we’re linking to and second is the alias for the link name.

    -
    -
    - - - - - -
    -
    Note
    -
    -
    Container Linking
    -
    -

    Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container.

    -
    -
    -

    In our case, target container (WildFly) can see information about source container (MySQL). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. For example, IP address of MySQL server is expoed at $DB_PORT_3306_TCP_ADDR and port of MySQL server is exposed at $DB_PORT_3306_TCP_PORT. These are then used to create the JDBC resource.

    -
    -
    -

    See more about container communication on the Docker website Linking Containers Together

    -
    -
    -
    -
  4. -
  5. -

    See the output as:

    -
    -
    -
    > curl http://$(docker-machine ip lab):8080/employees/resources/employees
    -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  6. -
-
-
-
-
-

7. Build and Deploy Java EE 6 Application (Ticket Monster)

-
-
-

Ticket Monster is an example application that focuses on Java EE6 - JPA 2, CDI, EJB 3.1 and JAX-RS along with HTML5 and jQuery Mobile. It is a moderately complex application that demonstrates how to build modern web applications optimized for mobile & desktop. TicketMonster is representative of an online ticketing broker - providing access to events (e.g. concerts, shows, etc) with an online booking application.

-
-
-

Apart from being a demo, TicketMonster provides an already existing application structure that you can use as a starting point for your app. You could try out your use cases, test your own ideas, or, contribute improvements back to the community.

-
-
-
-ticket monster tutorial architecture -
-
Figure 7. TicketMonster architecture
-
-
-

The application uses Java EE 6 services to provide business logic and persistence, utilizing technologies such as CDI, EJB 3.1 and JAX-RS, JPA 2. These services back the user-facing booking process, which is implemented using HTML5 and JavaScript, with support for mobile devices through jQuery Mobile.

-
-
-

The administration site is centered around CRUD use cases, so instead of writing everything manually, the business layer and UI are generated by Forge, using EJB 3.1, CDI and JAX-RS. For a better user experience, Twitter Bootstrap is used.

-
-
-

Monitoring sales requires staying in touch with the latest changes on the server side, so this part of the application will be developed in HTML5 and JavaScript using a polling solution.

-
-
-

7.1. Build Application

-
-

First thing, you’re going to do is to build the application from source. Create a directory for the source and change to it:

-
-
-
-
mkdir docker-java/
-cd docker-java/
-
-
-
-

And checkout the sources from the instructor’s git repository.

-
-
-
-
git clone -b WildFly-docker-test http://root:dockeradmin@classroom.example.com:10080/root/ticket-monster.git
-
-
-
-

-b WildFly-docker-test is a branch of Ticket Monster that contains a ``docker-test'' profile to run Arquillian Cube test. More on this later.

-
-
- - - - - -
-
Note
-
-You’re free to explore the application. Open it with with the favorite IDE of your choice. Find more background about the use-cases and how the application is designed at Ticket Monster Website. -
-
-
-

Copy the Maven lab-settings.xml file that you have downloaded from the instructor machine and place it inside docker-java directory.

-
-
-

When you’re ready, it is time to build the application. Switch to the checkout directory and run maven package.

-
-
-
-
cd docker-java/
-mvn -s lab-settings.xml -f ticket-monster/demo/pom.xml -Ppostgresql clean package
-
-
-
-

Congratulations! You just build the applications war file. Let’s deploy it!

-
-
-
-

7.2. Start Database Server

-
-

The application require an application server and a database server. This lab will use WildFly and Postgres for them respectively.

-
-
-

Start Postgres database as:

-
-
-
-
docker run --name db -d -p 5432:5432 -e POSTGRES_USER=ticketmonster -e POSTGRES_PASSWORD=ticketmonster-docker classroom.example.com:5000/postgres
-
-
-
-

This command starts a container named `db'' from the image in your instructor’s registry `classroom.example.com:5000/postgres. As this will not be present locally, it needs to be downloaded first. But you’ll have a very quick connection to the instructor registry and this shouldn’t take long.

-
-
-

The two -e options define environment variables which are read by the db at startup and allow us to access the database with this user and password.

-
-
-

Finally, the -d option tells docker to start a demon process. Which means, that the console window, you’re running this command in, will be available again after it is issued. If you skip this parameter, the console will be directly showing the output from the process.

-
-
-

-p option maps container ports to host ports and allows other containers on our host to access them.

-
-
-

This starts the database container. It can be confirmed as:

-
-
-
-
> docker ps
-CONTAINER ID        IMAGE                                           COMMAND                CREATED             STATUS              PORTS                                              NAMES
-047bab6a86fe        classroom.example.com:5000/postgres:latest             "/docker-entrypoint.   42 seconds ago      Up 3 seconds        0.0.0.0:5432->5432/tcp                             db
-
-
-
-

Server logs can be viewed as:

-
-
-
-
docker logs -f db
-
-
-
-

The -f flag keeps refreshing the logs and pushes new events directly out to the console.

-
-
-
-

7.3. Start Application Server

-
-

Start WildFly server as:

-
-
-
-
docker run -d --name wildfly -p 8080:8080 --link db:db -v /Users/youruser/tmp/deployments:/opt/jboss/wildfly/standalone/deployments/:rw classroom.example.com:5000/wildfly
-
-
-
-

Make sure to replace /Users/youruser/tmp/deployments to a directory on your local machine. Also, make sure this directory already exists.

-
-
-

This command starts a container named `wildfly''. `--link takes two parameters - first is name of the container we’re linking to and second is the alias for the link name.

-
-
- - - - - -
-
Note
-
-
Container Linking
-
-

Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container.

-
-
-

In our case, target container (WildFly) can see information about source container (Postgres). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container.

-
-
-

See more about container communication on the Docker website Linking Containers Together

-
-
-
-
-

The -v flag maps a directory from the host into the container. This will be the directory to put the deployments. rw ensures that the Docker container can write to it.

-
-
- - - - - -
-
Warning
-
-Windows users, please make sure to use -v /c/Users/ notation for drive letters. -
-
-
-

Check logs to verify if the server has started.

-
-
-
-
docker logs -f wildfly
-
-
-
-

And access the http://dockerhost:8080 with your webbrowser to make sure the instance is up and running.

-
-
-

Now you’re ready to deploy the application for the first time. Let’s use JBoss Developer Studio for this.

-
-
-
-

7.4. Configure JBoss Developer Studio

-
-

Start JBoss Developer Studio, if not already started.

-
-
-
    -
  1. -

    Create a server adapter

    -
    -
    -jbds1 -
    -
    Figure 8. Server adapter
    -
    -
  2. -
  3. -

    Assign or create a WildFly 8.x runtime (changed properties are highlighted.)

    -
    -
    -jbds2 -
    -
    Figure 9. WildFly Runtime Properties
    -
    -
  4. -
  5. -

    Setup server properties as shown in the following image.

    -
    -

    Two properties on the left are automatically propagated from the previous dialog. Additional two properties on the right side are required to disable to keep deployment scanners in sync with the server.

    -
    -
    -
    -jbds3 -
    -
    Figure 10. Server properties
    -
    -
  6. -
  7. -

    Specify a custom deployment folder on Deployment tab of Server Editor

    -
    -
    -jbds4 -
    -
    Figure 11. Server Editor
    -
    -
  8. -
  9. -

    Right-click on the newly created server adapter and click ``Start''.

    -
    -
    -jbds5 -
    -
    Figure 12. Start Server
    -
    -
  10. -
-
-
-
-

7.5. Deploy Application Using Shared Volumes

-
-

Open Ticket Monster application source code. Right-click on the project, select ``Run on Server'' and chose the previously created server.

-
-
-

The project runs and displays the start page of Ticket Monster application.

-
-
-
-jbds6 -
-
Figure 13. Start Server
-
-
-

Congratulations! You’ve just deployed your first application to WildFly running in a Docker container from JBoss Developer Studio.

-
-
-

Stop WildFly container when you’re done.

-
-
-
-
docker stop wildfly
-
-
-
-
-

7.6. Deploy Application Using CLI (OPTIONAL)

-
-

The Command Line Interface (CLI) is a tool for connecting to WildFly instances to manage all tasks from command line environment. Some of the tasks that you can do using the CLI are:

-
-
-
    -
  1. -

    Deploy/Undeploy web application in standalone/Domain Mode.

    -
  2. -
  3. -

    View all information about the deployed application on runtime.

    -
  4. -
  5. -

    Start/Stop/Restart Nodes in respective mode i.e. Standalone/Domain.

    -
  6. -
  7. -

    Adding/Deleting resource or subsystems to servers.

    -
  8. -
-
-
-

Lets use the CLI to deploy Ticket Monster to WildFly running in the container.

-
-
-
    -
  1. -

    CLI needs to be locally installed and comes as part of WildFly. Download WildFly 8.2 from http://classroom.example.com:8082/downloads/wildfly-8.2.0.Final.zip. Unzip into a folder of your choice (e.g. /Users/arungupta/tools/). This will create wildfly-8.2.0.Final directory here. This folder is named $WIDLFY_HOME from here on. Make sure to add the /Users/arungupta/tools/wildfly-8.2.0.Final/bin to your $PATH.

    -
    -
    -
    # Windows Example
    -set PATH=%PATH%;%WILDFLY_HOME%/bin
    -
    -
    -
  2. -
  3. -

    Run the ``wildfly-management'' image with fixed port mapping as explained in Fixed Port Mapping.

    -
  4. -
  5. -

    Run the jboss-cli command and connect to the WildFly instance.

    -
    -
    -
    cd %WIDLFY_HOME%/bin
    -./jboss-cli.sh --controller=dockerhost:9990  -u=admin -p=docker#admin -c
    -
    -
    -
    -

    This will show the output as:

    -
    -
    -
    -
    [standalone@dockerhost:9990 /]
    -
    -
    -
  6. -
  7. -

    Deploy the application as:

    -
    -
    -
    deploy <TICKET_MONSTER_PATH>/ticket-monster.war --force
    -
    -
    -
  8. -
-
-
-

Now you’ve sucessfully used the CLI to remote deploy the Ticket Monster application to WildFly running as docker container.

-
-
-

And again, keep the container running, we’re going to look into the last deployment option you have.

-
-
-
-

7.7. Deploy Application Using Web Console (OPTIONAL)

-
-

WildFly comes with a web-based administration console. It also relies on the same management APIs that we’ve already been using via JBoss Developer Tools and the CLI. It does provide a nice web-based way to administrate your instance and if you’ve already exposed the container ports, you can simply access it via the URL: http://dockerhost:9990 in your web browser.

-
-
-
-console1 -
-
Figure 14. WildFly Web Console
-
-
-

Username and password credentials are shown in [WildFly_Administration_Credentials]. Now navigate through the console and execute the following steps to deploy the application:

-
-
-
    -
  1. -

    Go to the ``Deployments'' tab.

    -
  2. -
  3. -

    Click on ``Add'' button.

    -
  4. -
  5. -

    On Step 1/2: Deployment Selection'' screen, select the <TICKET_MONSTER_PATH>/ticket-monster.war file on your computer and click Next''. This would be ticket-monster/demo/target/ticket-monster.war from Build Application.

    -
  6. -
  7. -

    On the Step 2/2: Verify Deployment Names'' screen, select Enable'' checkbox, and click on ``Save''.

    -
  8. -
-
-
-

This will complete the deployment of Ticket Monster using Admin Console.

-
-
-
-

7.8. Deploy Application Using Management API (OPTIONAL)

-
-

A standalone WildFly process, process can be configured to listen for remote management requests using its ``native management interface''. The CLI tool that comes with the application server uses this interface, and user can develop custom clients that use it as well. In order to use this, WildFly management interface listen IP needs to be changed from 127.0.0.1 to 0.0.0.0 which basically means, that it is not only listening on the localhost but also on all publicly assigned IP addresses.

-
-
-
    -
  1. -

    Start another WildFly instance again:

    -
    -
    -
    docker run -d --name wildflymngm -p 8080:8080 -p 9990:9990 --link db:db classroom.example.com:5000/wildfly-management
    -
    -
    -
    -

    There is no mapped volume in this case but an additional port exposed. The WildFly image that is used makes it easier for you to play around with the deployment via the management API. It has a tweaked start script which changes the management interface according to the behavior described in the first sentence.

    -
    -
  2. -
  3. -

    Create another new server adapter in JBoss Developer Studio.

    -
    -
    -jbds7 -
    -
    Figure 15. Create New Server Adapter
    -
    -
  4. -
  5. -

    Keep the defaults in the adapter properties.

    -
    -
    -jbds8 -
    -
    Figure 16. Adapter Properties
    -
    -
  6. -
  7. -

    Set up server properties by specifying the admin credentials (docker#admin). Note, you need to delete the existing password and use this instead:

    -
    -
    -jbds9 -
    -
    Figure 17. Management Login Credentials
    -
    -
  8. -
  9. -

    Right-click on the newly created server adapter and click Start''. Status quickly changes to Started, Synchronized'' as shown.

    -
    -
    -jbds10 -
    -
    Figure 18. Synchronized WildFly Server
    -
    -
  10. -
  11. -

    Right-click on the Ticket Monster project, select ``Run on Server'' and choose this server. The project runs and displays the start page of ticket-monster.

    -
  12. -
  13. -

    Stop WildFly when you’re done.

    -
    -
    -
    docker stop wildflymngm
    -
    -
    -
  14. -
-
-
-
-
-
-

8. Docker Maven Plugin

-
-
-

Maven plugin allows you to manage Docker images and containers from pom.xml. It comes with predefined goals:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GoalDescription

docker:start

Create and start containers

docker:stop

Stop and destroy containers

docker:build

Build images

docker:push

Push images to a registry

docker:remove

Remove images from local docker host

docker:logs

Show container logs

-
-

8.1. Run Java EE Application

-
-
    -
  1. -

    Clone the workspace as:

    -
    -
    -
    git clone https://github.com/javaee-samples/javaee7-docker-maven.git
    -
    -
    -
  2. -
  3. -

    Build the image as:

    -
    -
    -
    mvn package -Pdocker
    -
    -
    -
  4. -
  5. -

    Run the container as:

    -
    -
    -
    mvn install -Pdocker
    -
    -
    -
  6. -
  7. -

    Access your application at http://dockerhost:8080/javaee7-docker-maven/resources/persons.

    -
  8. -
-
-
-
-

8.2. Understand Plugin Configuration

-
-

pom.xml is updated to include docker-maven-plugin as:

-
-
-
-
<plugin>
-    <groupId>org.jolokia</groupId>
-    <artifactId>docker-maven-plugin</artifactId>
-    <version>0.11.5</version>
-    <configuration>
-        <images>
-            <image>
-                <alias>user</alias>
-                <name>arungupta/javaee7-docker-maven</name>
-                <build>
-                    <from>arungupta/wildfly:8.2</from>
-                    <assembly>
-                        <descriptor>assembly.xml</descriptor>
-                        <basedir>/</basedir>
-                    </assembly>
-                    <ports>
-                        <port>8080</port>
-                    </ports>
-                </build>
-                <run>
-                    <ports>
-                        <port>8080:8080</port>
-                    </ports>
-                </run>
-            </image>
-        </images>
-    </configuration>
-    <executions>
-        <execution>
-            <id>docker:build</id>
-            <phase>package</phase>
-            <goals>
-                <goal>build</goal>
-            </goals>
-        </execution>
-        <execution>
-            <id>docker:start</id>
-            <phase>install</phase>
-            <goals>
-                <goal>start</goal>
-            </goals>
-        </execution>
-    </executions>
-</plugin>
-
-
-
-

Each image configuration has three parts:

-
-
-
    -
  1. -

    Image name and alias

    -
  2. -
  3. -

    <build> that defines how the image is created. Base image, build artifacts and their dependencies, ports to be exposed, etc to be included in the image are specified here. Assembly descriptor format is used to specify the artifacts to be included and is defined in the src/main/docker directory.

    -
    -

    assembly.xml in our case looks like:

    -
    -
    -
    -
    <assembly . . .>
    -  <id>javaee7-docker-maven</id>
    -  <dependencySets>
    -    <dependencySet>
    -      <includes>
    -        <include>org.javaee7.sample:javaee7-docker-maven</include>
    -      </includes>
    -      <outputDirectory>/opt/jboss/wildfly/standalone/deployments/</outputDirectory>
    -      <outputFileNameMapping>javaee7-docker-maven.war</outputFileNameMapping>
    -    </dependencySet>
    -  </dependencySets>
    -</assembly>
    -
    -
    -
  4. -
  5. -

    <run> that defines how the container is run. Ports that need to be exposed are specified here.

    -
  6. -
-
-
-

In addition, package phase is tied to docker:build goal and install phase is tied to docker:start goal.

-
-
-
-
-
-

9. Docker Tools in Eclipse

-
-
-

The Docker tooling is aimed at providing at minimum the same basic level features as the command-line interface, but also provide some advantages by having access to a full fledged UI.

-
-
-

9.1. Install Docker Tools Plugins

-
-

As this is still in early access stage, you will have to install it first:

-
-
-
    -
  1. -

    Download and Install JBoss Developer Studio 9.0 Beta 2, take defaults through out the installation.

    -
    -

    Alternatively, download Eclipse Mars latest build and configure JBoss Tools plugin from the update site http://download.jboss.org/jbosstools/updates/nightly/mars/.

    -
    -
  2. -
  3. -

    Open JBoss Developer Studio 9.0 Nightly

    -
  4. -
  5. -

    Add a new site using the menu items: Help'' > Install New Software…​'' > Add…​''. Specify the Name:'' as Docker Nightly'' and Location:'' as http://download.eclipse.org/linuxtools/updates-docker-nightly/.

    -
    -
    -jbds docker tools1 -
    -
    Figure 19. Add Docker Tooling To JBoss Developer Studio
    -
    -
  6. -
  7. -

    Expand Linux Tools, select Docker Client'' and Docker Tooling''.

    -
    -
    -jbds docker tools nightly setup -
    -
    Figure 20. Add Docker Tooling
    -
    -
  8. -
  9. -

    Click on Next >'', Next >'', accept the terms of the license agreement, and click on ``Finish''. This will complete the installation of plugins.

    -
    -

    Restart the IDE for the changes to take effect.

    -
    -
  10. -
-
-
-
-

9.2. Docker Explorer

-
-

The Docker Explorer provides a wizard to establish a new connection to a Docker daemon. This wizard can detect default settings if the user’s machine runs Docker natively (such as in Linux) or in a VM using Boot2Docker (such as in Mac or Windows). Both Unix sockets on Linux machines and the REST API on other OSes are detected and supported. The wizard also allows remote connections using custom settings.

-
-
-
    -
  1. -

    Use the menu Window'', Show View'', Other…​''. Type docker'' to see the output as:

    -
    -
    -jbds docker tools docker view -
    -
    -
  2. -
  3. -

    Select ``Docker Explorer'' to open Docker Explorer.

    -
    -
    -jbds docker tools docker explorer view -
    -
    -
  4. -
  5. -

    Click on the link in this window to create a connection to Docker Host. Specify the settings as shown:

    -
    -
    -jbds docker tools2 -
    -
    Figure 21. Docker Explorer
    -
    -
    -

    Make sure to get IP address of the Docker Host as:

    -
    -
    -
    -
    docker-machine ip lab
    -
    -
    -
    -

    Also, make sure to specify the correct directory for .docker on your machine.

    -
    -
  6. -
  7. -

    Click on ``Test Connection'' to check the connection. This should show the output as:

    -
    -
    -jbds docker tools test connection output -
    -
    Figure 22. Docker Explorer
    -
    -
    -

    Click on OK'' and Finish'' to exit out of the wizard.

    -
    -
  8. -
  9. -

    Docker Explorer itself is a tree view that handles multiple connections and provides users with quick overview of the existing images and containers.

    -
    -
    -jbds docker tools3 -
    -
    Figure 23. Docker Explorer Tree View
    -
    -
  10. -
  11. -

    Customize the view by clicking on the arrow in toolbar:

    -
    -
    -jbds docker tools customize view option -
    -
    Figure 24. Docker Explorer Customize View
    -
    -
    -

    Built-in filters can show/hide intermediate and `dangling' images, as well as stopped containers.

    -
    -
    -
    -jbds docker tools customize view wizard -
    -
    Figure 25. Docker Explorer Customize View Wizard
    -
    -
  12. -
-
-
-
-

9.3. Docker Images

-
-

The Docker Images view lists all images in the Docker host selected in the Docker Explorer view. This view allows user to manage images, including:

-
-
-
    -
  1. -

    Pull/push images from/to the Docker Hub Registry (other registries will be supported as well, #469306)

    -
  2. -
  3. -

    Build images from a Dockerfile

    -
  4. -
  5. -

    Create a container from an image

    -
  6. -
-
-
-

Lets take a look at it.

-
-
-
    -
  1. -

    Use the menu Window'', Show View'', Other…​'', select Docker Images''. It shows the list of images on Docker Host:

    -
    -
    -jbds docker tools4 -
    -
    Figure 26. Docker Images View
    -
    -
  2. -
  3. -

    Right-click on the image ending with ``wildfly:latest'' and click on the green arrow in the toolbar. This will show the following wizard:

    -
    -
    -jbds docker tools run container wizard -
    -
    Figure 27. Docker Run Container Wizard
    -
    -
    -

    By default, all exports ports from the image are mapped to random ports on the host interface. This setting can be changed by unselecting the first checkbox and specify exact port mapping.

    -
    -
    -

    Click on ``Finish'' to start the container.

    -
    -
  4. -
  5. -

    When the container is started, all logs are streamed into Eclipse Console:

    -
    -
    -jbds docker tools5 -
    -
    Figure 28. Docker Container Logs
    -
    -
  6. -
-
-
-
-

9.4. Docker Containers

-
-

Docker Containers view lets the user manage the containers. The view toolbar provides commands to start, stop, pause, unpause, display the logs and kill containers.

-
-
-
    -
  1. -

    Use the menu Window'', Show View'', Other…​'', select Docker Containers''. It shows the list of running containers on Docker Host:

    -
    -
    -jbds docker tools6 -
    -
    Figure 29. Docker Containers View
    -
    -
  2. -
  3. -

    Pause the container by clicking on the pause'' button in the toolbar (#469310). Show the complete list of containers by clicking on the View Menu'', ``Show all containers''.

    -
    -
    -jbds docker tools all containers -
    -
    Figure 30. All Docker Containers
    -
    -
  4. -
  5. -

    Select the paused container, and click on the green arrow in the toolbar to restart the container.

    -
  6. -
  7. -

    Right-click on any running container and select ``Display Log'' to view the log for this container.

    -
    -
    -jbds docker tools display log -
    -
    Figure 31. Eclipse Properties View
    -
    -
  8. -
-
-
-

TODO: Users can also attach an Eclipse console to a running Docker container to follow the logs and use the STDIN to interact with it.

-
-
-
-

9.5. Details on Images and Containers

-
-

Eclipse Properties view is used to provide more information about the containers and images.

-
-
-
    -
  1. -

    Just open the Properties View and click on a Connection, Container, or Image in any of the Docker Explorer View, Docker Containers View, or Docker Images View. This will fill in data in the Properties view.

    -
    -

    Info view is shown as:

    -
    -
    -
    -jbds docker tools properties info -
    -
    Figure 32. Docker Container Properties View Info
    -
    -
    -

    Inspect view is shown as:

    -
    -
    -
    -jbds docker tools properties inspect -
    -
    Figure 33. Docker Container Properties View Inspect
    -
    -
  2. -
-
-
-
-
-
-

10. Test Java EE Applications on Docker

-
-
-

Testing Java EE applications is a very important aspect. Especially when it comes to in-container tests, JBoss Arquillian is well known to make this very easy for Java EE application servers. Picking up where unit tests leave off, Arquillian handles all the plumbing of container management, deployment and framework initialization so you can focus on the task at hand, writing your tests.

-
-
-

With Arquillian, you can use WildFly remote container adapter and connect to any WildFly instance running in a Docker container. But this wouldn’t help with the Docker container lifycycle management.

-
-
-

Arquillian Cube, an extension of Arquillian, allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually. This extension allows to start a Docker container with a server installed, deploy the required deployable file within it and execute Arquillian tests.

-
-
-

The key point here is that if Docker is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before.

-
-
-
    -
  1. -

    Check out the workspace:

    -
    -
    -
    git clone http://github.com/javaee-samples/javaee-arquillian-cube
    -
    -
    -
  2. -
  3. -

    Edit src/test/resources/arquillian.xml file and change the IP address specified in serverUri property value to point to your Docker host’s IP. This can be found out as:

    -
    -
    -
    docker-machine ip lab
    -
    -
    -
  4. -
  5. -

    Run the tests as:

    -
    -
    -
    mvn test
    -
    -
    -
    -

    This will create a container using the image defined in src/test/resources/wildfly/Dockerfile. The container qualifier in arquillian.xml defines the directory name in src/test/resources directory.

    -
    -
    - - - - - -
    -
    Note
    -
    -
    -

    A pre-built image can be used by specifying:

    -
    -
    -
    -
    wildfly:
    -  image: jboss/wildfly
    -
    -
    -
    -

    instead of

    -
    -
    -
    -
    wildfly:
    -  buildImage:
    -    dockerfileLocation: src/test/resources/wildfly
    -
    -
    -
    -
    -
    -

    By default, the ``cube'' profile is activated and this includes all the required dependencies.

    -
    -
    -

    The result is shown as:

    -
    -
    -
    -
    Running org.javaee7.sample.PersonDatabaseTest
    -Jun 16, 2015 9:23:04 AM org.jboss.arquillian.container.impl.MapObject populate
    -WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.remote.RemoteContainerConfiguration
    -Unused property entries: {target=wildfly:8.1.0.Final:remote}
    -Supported property names: [managementAddress, password, managementPort, managementProtocol, username]
    -Jun 16, 2015 9:23:13 AM org.xnio.Xnio <clinit>
    -INFO: XNIO version 3.2.0.Beta4
    -Jun 16, 2015 9:23:13 AM org.xnio.nio.NioXnio <clinit>
    -INFO: XNIO NIO Implementation Version 3.2.0.Beta4
    -Jun 16, 2015 9:23:13 AM org.jboss.remoting3.EndpointImpl <clinit>
    -INFO: JBoss Remoting version (unknown)
    -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.406 sec - in org.javaee7.sample.PersonDatabaseTest
    -
    -Results :
    -
    -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    -
    -[INFO] ------------------------------------------------------------------------
    -[INFO] BUILD SUCCESS
    -[INFO] ------------------------------------------------------------------------
    -
    -
    -
  6. -
  7. -

    In arquillian.xml, add the following property:

    -
    -
    -
    <property name="connectionMode">STARTORCONNECT</property>
    -
    -
    -
    -

    This bypasses the create/start Cube commands if a Docker Container with the same name is already running on the target system.

    -
    -
    -

    This allows you to prestart the containers manually during development and just connect to them to avoid the extra cost of starting the Docker Containers for each test run. This assumes you are not changing the actual definition of the Docker Container itself.

    -
    -
  8. -
-
-
-
-
-

11. Multiple Containers Using Docker Compose

-
-
-
-Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running. -
-
-— github.com/docker/compose -
-
-
-

An application using Docker containers will typically consist of multiple containers. With Docker Compose, there is no need to write shell scripts to start your containers. All the containers are defined in a configuration file using services, and then docker-compose script is used to start, stop, and restart the application and all the services in that application, and all the containers within that service. The complete list of commands is:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandPurpose

build

Build or rebuild services

help

Get help on a command

kill

Kill containers

logs

View output from containers

port

Print the public port for a port binding

ps

List containers

pull

Pulls service images

restart

Restart services

rm

Remove stopped containers

run

Run a one-off command

scale

Set number of containers for a service

start

Start services

stop

Stop services

up

Create and start containers

-
-

Docker Compose script is only available for OSX and Linux. https://github.com/arun-gupta/docker-java/issues/3 is used for tracking Docker Compose on Windows.

-
-
-

11.1. Configuration File

-
-
    -
  1. -

    Entry point to Compose is docker-compose.yml. Lets use the following file:

    -
    -
    -
    mysqldb:
    -  image: classroom.example.com:5000/mysql
    -  environment:
    -    MYSQL_DATABASE: sample
    -    MYSQL_USER: mysql
    -    MYSQL_PASSWORD: mysql
    -    MYSQL_ROOT_PASSWORD: supersecret
    -mywildfly:
    -  image: classroom.example.com:5000/wildfly-mysql-javaee7
    -  links:
    -    - mysqldb:db
    -  ports:
    -    - 8080:8080
    -
    -
    -
    -

    This file is available in ../attendees/docker-compose.yml and shows:

    -
    -
    -
      -
    1. -

      Two services are defined by the name mysqldb and mywildfly

      -
    2. -
    3. -

      Image name for each service is defined using image

      -
    4. -
    5. -

      Environment variables for the MySQL container are defined in environment

      -
    6. -
    7. -

      MySQL container is linked with WildFly container using links

      -
    8. -
    9. -

      Port forwarding is achieved using ports

      -
    10. -
    -
    -
  2. -
-
-
-
-

11.2. Start Services

-
-
    -
  1. -

    All the services can be started, in detached mode, by giving the command:

    -
    -
    -
    docker-compose up -d
    -
    -
    -
    -

    And this shows the output as:

    -
    -
    -
    -
    Creating attendees_mysqldb_1...
    -Creating attendees_mywildfly_1...
    -
    -
    -
    -

    An alternate compose file name can be specified using -f.

    -
    -
    -

    An alternate directory where the compose file exists can be specified using -p.

    -
    -
  2. -
  3. -

    Started services can be verified as:

    -
    -
    -
    > docker-compose ps
    -        Name                       Command               State                Ports
    --------------------------------------------------------------------------------------------------
    -attendees_mysqldb_1     /entrypoint.sh mysqld            Up      3306/tcp
    -attendees_mywildfly_1   /opt/jboss/wildfly/customi ...   Up      0.0.0.0:8080->8080/tcp, 9990/tcp
    -
    -
    -
    -

    This provides a consolidated view of all the services started, and containers within them.

    -
    -
    -

    Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual docker ps command:

    -
    -
    -
    -
    > docker ps
    -CONTAINER ID        IMAGE                                    COMMAND                CREATED             STATUS              PORTS                              NAMES
    -3598e545bd2f        arungupta/wildfly-mysql-javaee7:latest   "/opt/jboss/wildfly/   59 seconds ago      Up 58 seconds       0.0.0.0:8080->8080/tcp, 9990/tcp   attendees_mywildfly_1
    -b8cf6a3d518b        mysql:latest                             "/entrypoint.sh mysq   2 minutes ago       Up 2 minutes        3306/tcp                           attendees_mysqldb_1
    -
    -
    -
  4. -
  5. -

    Service logs can be seen as:

    -
    -
    -
    > docker-compose logs
    -Attaching to attendees_mywildfly_1, attendees_mysqldb_1
    -mywildfly_1 | => Starting WildFly server
    -mywildfly_1 | => Waiting for the server to boot
    -mywildfly_1 | =========================================================================
    -mywildfly_1 |
    -mywildfly_1 |   JBoss Bootstrap Environment
    -mywildfly_1 |
    -mywildfly_1 |   JBOSS_HOME: /opt/jboss/wildfly
    -mywildfly_1 |
    -mywildfly_1 |   JAVA: /usr/lib/jvm/java/bin/java
    -mywildfly_1 |
    -mywildfly_1 |   JAVA_OPTS:  -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
    -mywildfly_1 |
    -
    -. . .
    -
    -mywildfly_1 | 15:40:20,866 INFO  [org.jboss.resteasy.spi.ResteasyDeployment] (MSC service thread 1-2) Deploying javax.ws.rs.core.Application: class org.javaee7.samples.employees.MyApplication
    -mywildfly_1 | 15:40:20,914 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017534: Registered web context: /employees
    -mywildfly_1 | 15:40:21,032 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "employees.war" (runtime-name : "employees.war")
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 9572ms - Started 280 of 334 services (92 services are lazy, passive or on-demand)
    -mysqldb_1   | Running mysql_install_db
    -mysqldb_1   | 2015-06-05 15:38:31 0 [Note] /usr/sbin/mysqld (mysqld 5.6.25) starting as process 27 ...
    -mysqldb_1   | 2015-06-05 15:38:31 27 [Note] InnoDB: Using atomics to ref count buffer pool pages
    -
    -. . .
    -
    -mysqldb_1   | 2015-06-05 15:38:40 1 [Note] Event Scheduler: Loaded 0 events
    -mysqldb_1   | 2015-06-05 15:38:40 1 [Note] mysqld: ready for connections.
    -mysqldb_1   | Version: '5.6.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    -mysqldb_1   | 2015-06-05 15:40:18 1 [Warning] IP address '172.17.0.24' could not be resolved: Name or service not known
    -
    -
    -
  6. -
-
-
-
-

11.3. Verify Application

-
-
    -
  1. -

    Access the application at http://dockerhost:8080/employees/resources/employees/. This is shown in the browser as:

    -
  2. -
-
-
-
-docker compose output -
-
Figure 34. Output From Servers Run Using Docker Compose
-
-
-
-

11.4. Stop Services

-
-
    -
  1. -

    Stop the services as:

    -
    -
    -
    > docker-compose stop
    -Stopping attendees_mywildfly_1...
    -Stopping attendees_mysqldb_1...
    -
    -
    -
  2. -
-
-
- -
-
-
-

12. Java EE Application on Mod Cluster

-
-
-

A frequent requirement for Java EE based applications is running them on a cluster of application server. While setup and test can be complicated on developer machines, this is where Docker can play to it’s full potential. With the help of images and automatic port mapping, we’re ready to test Ticket Monster on a couple of WildFly instances and add and remove them randomly.

-
-
-

The diagram below shows what will be achieved in this section:

-
-
-
-wildfly cluster1 -
-
Figure 35. Standalone Cluster with WildFly and mod_cluster
-
-
-
    -
  1. -

    Start Apache HTTPD server

    -
    -
    -
    docker run -d --name modcluster -p 80:80 classroom.example.com:5000/mod_cluster
    -
    -
    -
  2. -
  3. -

    Open http://dockerhost/mod_cluster_manager in your browser to see the empty console as:

    -
    -
    -wildfly cluster2 -
    -
    Figure 36. Apache HTTPD runing mod_cluster_manager interface
    -
    -
  4. -
  5. -

    Start Postgres database container, if not already running:

    -
    -
    -
    docker run --name db -d -p 5432:5432 -e POSTGRES_USER=ticketmonster -e POSTGRES_PASSWORD=ticketmonster-docker classroom.example.com:5000/postgres
    -
    -
    -
  6. -
  7. -

    Start the first WildFly instance:

    -
    -
    -
    docker run -d --name server1 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly
    -
    -
    -
    -

    Besides linking the database container using --link db:db, we also link the ``modcluster'' container. This should be done rather quickly and if you now revisit the mod_cluster_manager in your browser, then you can see that the first server was registered with the loadbalancer:

    -
    -
    -
    -wildfly cluster3 -
    -
    Figure 37. First WildFly instance registered with Load Balancer
    -
    -
  8. -
  9. -

    To make sure the Ticket Monster application is also running just visit http://dockerhost/ticket-monster and you will be presented with the Ticket Monster welcome screen.

    -
    -
    -wildfly cluster4 -
    -
    Figure 38. Clustered Ticket Monster Application
    -
    -
  10. -
  11. -

    Start as many WildFly instances as you want (and your computer memory can handle):

    -
    -
    -
    docker run -d --name server2 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly
    -docker run -d --name server3 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly
    -docker run -d --name server4 --link db:db --link modcluster:modcluster classroom.example.com:5000/ticketmonster-pgsql-wildfly
    -
    -
    -
  12. -
  13. -

    Stop some servers:

    -
    -
    -
    docker stop server1
    -docker stop server3
    -
    -
    -
    -

    Ensure that the application is still accessible at http://dockerhost/ticket-monster.

    -
    -
  14. -
-
-
-
-
-

13. Java EE Application on Docker Swarm Cluster

-
-
-

Docker Swarm solves one of the fundamental limitations of Docker where the containers could only run on a single Docker host. Docker Swarm is native clustering for Docker. It turns a pool of Docker hosts into a single, virtual host.

-
-
-
-swarm1 -
-
Figure 39. Key Components of Docker Swarm
-
-
-

Swarm Manager: Docker Swarm has a Master or Manager, that is a pre-defined Docker Host, and is a single point for all administration. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with #598. TODO: ADD LINK.

-
-
-

Swarm Nodes: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a node agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node.

-
-
-

Scheduler Strategy: Different scheduler strategies (binpack'', spread'' (default), and ``random'') can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm.

-
-
-

Node Discovery Service: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and zookeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and #660 will discuss this.

-
-
-

Standard Docker API: Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster.

-
-
-

There are lots of other concepts but these are the main ones.

-
-
-
    -
  1. -

    Create a Swarm cluster. The easiest way of using Swarm is, by using the official Docker image:

    -
    -
    -
    docker run swarm create
    -
    -
    -
    -

    This command returns a <TOKEN> and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub.

    -
    -
    - - - - - -
    -
    Note
    -
    -Make sure to note this cluster id now as there is no means to list it later. -
    -
    -
  2. -
  3. -

    Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let’s create a Swarm Master next:

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<TOKEN> swarm-master
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in the previous step.

    -
    -
    -

    --swarm configures the machine with Swarm, --swarm-master configures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster.

    -
    -
  4. -
  5. -

    Connect to this newly created master and find some more information about it:

    -
    -
    -
    eval "$(docker-machine env swarm-master)"
    -docker info
    -
    -
    -
    - - - - - -
    -
    Note
    -
    -If you’re on Windows, use the docker-machine env swarm-master command only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/". -
    -
    -
    -

    This will show the output as:

    -
    -
    -
    -
    > docker info
    -Containers: 2
    -Images: 7
    -Storage Driver: aufs
    - Root Dir: /mnt/sda1/var/lib/docker/aufs
    - Backing Filesystem: extfs
    - Dirs: 11
    - Dirperm1 Supported: true
    -Execution Driver: native-0.2
    -Kernel Version: 4.0.3-boot2docker
    -Operating System: Boot2Docker 1.6.2 (TCL 5.4); master : 4534e65 - Wed May 13 21:24:28 UTC 2015
    -CPUs: 1
    -Total Memory: 998.1 MiB
    -Name: swarm-master
    -ID: USSA:35LS:WVRN:GKAZ:MLD4:XMQF:P7PL:VQ5D:7V4K:2QAH:5D2L:HC4K
    -Debug mode (server): true
    -Debug mode (client): false
    -Fds: 24
    -Goroutines: 37
    -System Time: Wed Jun 10 03:40:00 UTC 2015
    -EventsListeners: 1
    -Init SHA1: 7f9c6798b022e64f04d2aff8c75cbf38a2779493
    -Init Path: /usr/local/bin/docker
    -Docker Root Dir: /mnt/sda1/var/lib/docker
    -Username: arungupta
    -Registry: [https://index.docker.io/v1/]
    -Labels:
    - provider=virtualbox
    -
    -
    -
  6. -
  7. -

    Create Swarm nodes.

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-01
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in the previous step.

    -
    -
    -

    Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by --swarm-discovery token://…​ and specifying the cluster id obtained earlier.

    -
    -
  8. -
  9. -

    To make it a real cluster, let’s create a second node:

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-02
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in the previous step.

    -
    -
  10. -
  11. -

    List all the nodes / Docker machines, that has been created so far.

    -
    -
    -
    docker-machine ls
    -
    -
    -
    -

    This shows the output as:

    -
    -
    -
    -
    NAME            ACTIVE   DRIVER       STATE     URL                         SWARM
    -lab                      virtualbox   Running   tcp://192.168.99.103:2376
    -swarm-master    *        virtualbox   Running   tcp://192.168.99.107:2376   swarm-master (master)
    -swarm-node-01            virtualbox   Running   tcp://192.168.99.108:2376   swarm-master
    -swarm-node-02            virtualbox   Running   tcp://192.168.99.109:2376   swarm-master
    -
    -
    -
    -

    The machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example, lab'' is a standalone machine where as all other machines are part of the swarm-master'' cluster. The Swarm master is also identified by (master) in the SWARM column.

    -
    -
  12. -
  13. -

    Connect to the Swarm cluster and find some information about it:

    -
    -
    -
    eval "$(docker-machine env --swarm swarm-master)"
    -docker info
    -
    -
    -
    -

    This shows the output as:

    -
    -
    -
    -
    > docker info
    -Containers: 4
    -Strategy: spread
    -Filters: affinity, health, constraint, port, dependency
    -Nodes: 3
    - swarm-master: 192.168.99.107:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    - swarm-node-01: 192.168.99.108:2376
    -  └ Containers: 1
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    - swarm-node-02: 192.168.99.109:2376
    -  └ Containers: 1
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    -
    -
    -
    -

    There are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers:

    -
    -
  14. -
  15. -

    List nodes in the cluster with the following command:

    -
    -
    -
    docker run swarm list token://<TOKEN>
    -
    -
    -
    -

    This shows the output as:

    -
    -
    -
    -
    > docker run swarm list token://b9d9da9198c0facbeeae302242fb65a5
    -192.168.99.109:2376
    -192.168.99.108:2376
    -192.168.99.107:2376
    -
    -
    -
  16. -
-
-
-

The complete cluster is in place now, and we need to deploy the Java EE application to it.

-
-
-

Swarm takes care for the distribution of the deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in Deploy Java EE 7 Application (Container Linking).

-
-
-
    -
  1. -

    Start MySQL server as:

    -
    -
    -
    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
    -
    -
    -
    -

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

    -
    -
  2. -
  3. -

    Start WildFly and deploy Java EE 7 application as:

    -
    -
    -
    docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
    -
    -
    -
    -

    This is using the Docker Container Linking explained earlier.

    -
    -
  4. -
  5. -

    Check the state of the cluster as:

    -
    -
    -
    > docker info
    -Containers: 7
    -Strategy: spread
    -Filters: affinity, health, constraint, port, dependency
    -Nodes: 3
    - swarm-master: 192.168.99.107:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    - swarm-node-01: 192.168.99.108:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    - swarm-node-02: 192.168.99.109:2376
    -  └ Containers: 3
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.023 GiB
    -
    -
    -
    -

    ``swarm-node-02'' is running three containers and so lets look at the list of containers running there:

    -
    -
    -
    -
    > eval "$(docker-machine env swarm-node-02)"
    -> docker ps -a
    -CONTAINER ID        IMAGE                                    COMMAND                CREATED              STATUS              PORTS                    NAMES
    -f8022254703d        arungupta/wildfly-mysql-javaee7:latest   "/opt/jboss/wildfly/   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   mywildfly
    -7b6e9324c735        mysql:latest                             "/entrypoint.sh mysq   7 minutes ago        Up 7 minutes        0.0.0.0:3306->3306/tcp   mysqldb
    -6ed4c35c943b        swarm:latest                             "/swarm join --addr    12 minutes ago       Up 12 minutes       2375/tcp                 swarm-agent
    -
    -
    -
  6. -
  7. -

    Access the application as:

    -
    -
    -
    curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees
    -
    -
    -
    -

    to see the output as:

    -
    -
    -
    -
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  8. -
-
- -
-
-
-

14. Java EE Application on Kubernetes Cluster

-
-
-
-Kubernetes is an open source system for managing containerized applications across multiple hosts, providing basic mechanisms for deployment, maintenance, and scaling of applications. -
-
-— github.com/GoogleCloudPlatform/kubernetes/ -
-
-
-

Kubernetes, or ``k8s'' in short, allows the user to provide declarative primitives for the desired state, for example “need 5 WildFly servers and 1 MySQL server running”. Kubernetes self-healing mechanisms, such as auto-restarting, re-scheduling, and replicating containers then ensure this state is met. The user just define the state and Kubernetes ensures that the state is met at all times on the cluster.

-
-
-

How is it related to Docker?

-
-
-

Docker provides the lifecycle management of containers. A Docker image defines a build time representation of the runtime containers. There are commands to start, stop, restart, link, and perform other lifecycle methods on these containers. Kubernetes uses Docker to package, instantiate, and run containerized applications.

-
-
-

How does Kubernetes simplify containerized application deployment?

-
-
-

A typical application would have a cluster of containers across multiple hosts. For example, your web tier (for example Undertow) might run on a set of containers. Similarly, your application tier (for example, WildFly) would run on a different set of containers. The web tier would need to delegate the request to application tier. In some cases, or at least to begin with, you may have your web and application server packaged together in the same set of containers. The database tier would generally run on a separate tier anyway. These containers would need to talk to each other. Using any of the solutions mentioned above would require scripting to start the containers, and monitoring/bouncing if something goes down. Kubernetes does all of that for the user after the application state has been defined.

-
-
-

14.1. Key Concepts

-
-

At a very high level, there are three key concepts:

-
-
-
    -
  1. -

    Pods are the smallest deployable units that can be created, scheduled, and managed. Its a logical collection of containers that belong to an application.

    -
  2. -
  3. -

    Master is the central control point that provides a unified view of the cluster. There is a single master node that control multiple minions.

    -
  4. -
  5. -

    Minion is a worker node that run tasks as delegated by the master. Minions can run one or more pods. It provides an application-specific “virtual host” in a containerized environment.

    -
  6. -
-
-
-

A picture is always worth a thousand words and so this is a high-level logical block diagram for Kubernetes:

-
-
-
-kubernetes key concepts -
-
Figure 40. Kubernetes Key Concepts
-
-
-

After the 50,000 feet view, lets fly a little lower at 30,000 feet and take a look at how Kubernetes make all of this happen. There are a few key components at Master and Minion that make this happen.

-
-
-
    -
  1. -

    Replication Controller is a resource at Master that ensures that requested number of pods are running on minions at all times.

    -
  2. -
  3. -

    Service is an object on master that provides load balancing across a replicated group of pods. -Label is an arbitrary key/value pair in a distributed watchable storage that the Replication Controller uses for service discovery.

    -
  4. -
  5. -

    Kubelet Each minion runs services to run containers and be managed from the master. In addition to Docker, Kubelet is another key service installed there. It reads container manifests as YAML files that describes a pod. Kubelet ensures that the containers defined in the pods are started and continue running.

    -
  6. -
  7. -

    Master serves RESTful Kubernetes API that validate and configure Pod, Service, and Replication Controller.

    -
  8. -
-
-
-
-

14.2. Start Kubernetes Cluster

-
-
    -
  1. -

    In ``kubernetes'' directory, setup a cluster as:

    -
    -
    -
    cd kubernetes
    -
    -export KUBERNETES_PROVIDER=vagrant
    -./cluster/kube-up.sh
    -
    -
    -
    -

    The KUBERNETES_PROVIDER environment variable tells all of the various cluster management scripts which variant to use.

    -
    -
    - - - - - -
    -
    Note
    -
    -This will take a few minutes, so be patience! Vagrant will provision each machine in the cluster with all the necessary components to run Kubernetes. -
    -
    -
    -

    It shows the output as:

    -
    -
    -
    -
    Starting cluster using provider: vagrant
    -... calling verify-prereqs
    -... calling kube-up
    -Using credentials: vagrant:vagrant
    -
    -. . .
    -
    -Cluster validation succeeded
    -Done, listing cluster services:
    -
    -Kubernetes master is running at https://10.245.1.2
    -KubeDNS is running at https://10.245.1.2/api/v1beta3/proxy/namespaces/default/services/kube-dns
    -
    -
    -
    -

    Note down the address for Kubernetes master, https://10.245.1.2 in this case.

    -
    -
  2. -
  3. -

    Verify the Kubernetes cluster as:

    -
    -
    -
    kubernetes> vagrant status
    -Current machine states:
    -
    -master                    running (virtualbox)
    -minion-1                  running (virtualbox)
    -
    -This environment represents multiple VMs. The VMs are all listed
    -above with their current state. For more information about a specific
    -VM, run `vagrant status NAME`.
    -
    -
    -
    -

    By default, the Vagrant setup will create a single kubernetes-master and 1 kubernetes-minion. Each VM will take 1 GB, so make sure you have at least 2GB to 4GB of free memory (plus appropriate free disk space).

    -
    -
    - - - - - -
    -
    Note
    -
    -By default, only one minion is created. This can be manipulated by setting an environment variable NUM_MINIONS variable to an integer before invoking kube-up.sh script. -
    -
    -
    -

    By default, each VM in the cluster is running Fedora, Kubelet is installed into ``systemd'', and all other Kubernetes services are running as containers on Master.

    -
    -
  4. -
  5. -

    Access https://10.245.1.2 (or whatever IP address is assigned to your kubernetes cluster start up log). This may present the warning as shown below:

    -
    -
    -kubernetes master default output certificate -
    -
    -
    -

    Click on Advanced'' and then on Proceed to 10.245.1.2'' to see the output as:

    -
    -
    -
    -kubernetes master default output -
    -
    Figure 41. Kubernetes Output from Master
    -
    -
    -

    Use vagrant'' as the username and vagrant'' as the password.

    -
    -
    -

    Check the list of nodes as:

    -
    -
    -
    -
    > ./cluster/kubectl.sh get nodes
    -NAME         LABELS                              STATUS
    -10.245.1.3   kubernetes.io/hostname=10.245.1.3   Ready
    -
    -
    -
  6. -
  7. -

    Check the list of pods:

    -
    -
    -
    kubernetes> ./cluster/kubectl.sh get po
    -POD                                IP        CONTAINER(S)     IMAGE(S)                                                                   HOST                 LABELS                                                           STATUS    CREATED     MESSAGE
    -etcd-server-kubernetes-master                                                                                                            kubernetes-master/   <none>                                                           Running   2 minutes
    -                                             etcd-container   gcr.io/google_containers/etcd:2.0.9                                                                                                                              Running   2 minutes
    -kube-apiserver-kubernetes-master                                                                                                         kubernetes-master/   <none>                                                           Running   2 minutes
    -                                             kube-apiserver   gcr.io/google_containers/kube-apiserver:465b93ab80b30057f9c2ef12f30450c3                                                                                         Running   2 minutes
    -kube-dns-v1-lxdof                                                                                                                        10.245.1.3/          k8s-app=kube-dns,kubernetes.io/cluster-service=true,version=v1   Pending   2 minutes
    -                                             etcd             gcr.io/google_containers/etcd:2.0.9
    -                                             kube2sky         gcr.io/google_containers/kube2sky:1.7
    -                                             skydns           gcr.io/google_containers/skydns:2015-03-11-001
    -kube-scheduler-kubernetes-master                                                                                                         kubernetes-master/   <none>                                                           Running   2 minutes
    -                                             kube-scheduler   gcr.io/google_containers/kube-scheduler:d1f640dfb379f64daf3ae44286014821                                                                                         Running   2 minutes
    -
    -
    -
  8. -
  9. -

    Check the list of services running:

    -
    -
    -
    > ./cluster/kubectl.sh get se
    -NAME            LABELS                                                                           SELECTOR           IP(S)         PORT(S)
    -kube-dns        k8s-app=kube-dns,kubernetes.io/cluster-service=true,kubernetes.io/name=KubeDNS   k8s-app=kube-dns   10.247.0.10   53/UDP
    -                                                                                                                                  53/TCP
    -kubernetes      component=apiserver,provider=kubernetes                                          <none>             10.247.0.2    443/TCP
    -kubernetes-ro   component=apiserver,provider=kubernetes                                          <none>             10.247.0.1    80/TCP
    -
    -
    -
  10. -
  11. -

    Check the list of replication controllers:

    -
    -
    -
    > ./cluster/kubectl.sh get rc
    -CONTROLLER    CONTAINER(S)   IMAGE(S)                                         SELECTOR                      REPLICAS
    -kube-dns-v1   etcd           gcr.io/google_containers/etcd:2.0.9              k8s-app=kube-dns,version=v1   1
    -              kube2sky       gcr.io/google_containers/kube2sky:1.7
    -              skydns         gcr.io/google_containers/skydns:2015-03-11-001
    -
    -
    -
  12. -
-
-
-
-

14.3. Deploy Java EE Application

-
-

Pods, and the IP addresses assigned to them, are ephemeral. If a pod dies then Kubernetes will recreate that pod because of its self-healing features, but it might recreate it on a different host. Even if it is on the same host, a different IP address could be assigned to it. And so any application cannot rely upon the IP address of the pod.

-
-
-

Kubernetes services is an abstraction which defines a logical set of pods. A service is typically back-ended by one or more physical pods (associated using labels), and it has a permanent IP address that can be used by other pods/applications. For example, WildFly pod can not directly connect to a MySQL pod but can connect to MySQL service. In essence, Kubernetes service offers clients an IP and port pair which, when accessed, redirects to the appropriate backends.

-
-
-
-kubernetes services -
-
Figure 42. Kubernetes Services
-
-
- - - - - -
-
Note
-
-In this case, all the pods are running on a single minion. This is because, that is the default number for a Kubernetes cluster. The pod can very be on another minion if more minions exist in the cluster. -
-
-
-

Any Service that a Pod wants to access must be created before the Pod itself, or else the environment variables will not be populated.

-
-
-

14.3.1. Start MySQL Service

-
-
    -
  1. -

    Start MySQL service as:

    -
    -
    -
    ./cluster/kubectl.sh create -f ../../attendees/kubernetes/mysql-service.yaml
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    id: mysql
    -kind: Service
    -apiVersion: v1beta3
    -metadata:
    -  name: mysql
    -  labels:
    -    name: mysql
    -    context: docker-k8s-lab
    -spec:
    -  ports:
    -    - port: 3306
    -  selector:
    -    name: mysql
    -  labels:
    -    name: mysql
    -
    -
    -
  2. -
  3. -

    Check that the service is created:

    -
    -
    -
    > ./cluster/kubectl.sh get se -l context=docker-k8s-lab
    -NAME      LABELS                              SELECTOR     IP(S)            PORT(S)
    -mysql     context=docker-k8s-lab,name=mysql   name=mysql   10.247.141.208   3306/TCP
    -
    -
    -
    -

    Note that the label used during the creation is used to query the service.

    -
    -
    -

    When a Pod is run on a node, the kubelet adds a set of environment variables for each active Service.

    -
    -
    -

    It supports both Docker links compatible variables and simpler {SVCNAME}_SERVICE_HOST and {SVCNAME}_SERVICE_PORT variables, where the Service name is upper-cased and dashes are converted to underscores.

    -
    -
    -

    Our service name is `mysql'' and so `MYSQL_SERVICE_HOST and MYSQL_SERVICE_PORT variables are available to other pods.

    -
    -
  4. -
-
-
-

Send a Pull Request for #62.

-
-
-
-

14.3.2. Start MySQL Replication Controller

-
-
    -
  1. -

    Start MySQL replication controller as:

    -
    -
    -
    > ./cluster/kubectl.sh --v=5 create -f ../../attendees/kubernetes/mysql.yaml
    -I0616 19:41:55.441461    8346 defaults.go:174] creating security context for container mysql
    -replicationcontrollers/mysql
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    kind: ReplicationController
    -apiVersion: v1beta3
    -metadata:
    -  name: mysql
    -  labels:
    -    name: mysql
    -    context: docker-k8s-lab
    -spec:
    -  replicas: 1
    -  selector:
    -    name: mysql
    -  template:
    -    metadata:
    -      labels:
    -        name: mysql
    -        context: docker-k8s-lab
    -    spec:
    -      containers:
    -        - name: mysql
    -          image: mysql:latest
    -          env:
    -            - name: MYSQL_USER
    -              value: mysql
    -            - name: MYSQL_PASSWORD
    -              value: mysql
    -            - name: MYSQL_DATABASE
    -              value: sample
    -            - name: MYSQL_ROOT_PASSWORD
    -              value: supersecret
    -          ports:
    -            - containerPort: 3306
    -              hostPort: 3306
    -
    -
    -
    -

    Once again, the ``docker-k8s-lab'' label is used. This simplifies querying the created pods later on.

    -
    -
  2. -
  3. -

    Verify MySQL replication controller as:

    -
    -
    -
    > ./cluster/kubectl.sh get rc -l context=docker-k8s-lab
    -CONTROLLER   CONTAINER(S)   IMAGE(S)       SELECTOR     REPLICAS
    -mysql        mysql          mysql:latest   name=mysql   1
    -
    -
    -
  4. -
  5. -

    Check the status of MySQL pod as:

    -
    -
    -
    > ./cluster/kubectl.sh get po -l context=docker-k8s-lab
    -POD           IP        CONTAINER(S)   IMAGE(S)       HOST          LABELS                              STATUS    CREATED          MESSAGE
    -mysql-7lq67                                           10.245.1.3/   context=docker-k8s-lab,name=mysql   Pending   About a minute
    -                        mysql          mysql:latest
    -
    -
    -
  6. -
-
-
-
-

14.3.3. Start WildFly Replication Controller

-
-
    -
  1. -

    Start WildFly replication controller as:

    -
    -
    -
    > ./cluster/kubectl.sh --v=5 create -f ../../attendees/kubernetes/wildfly.yaml
    -I0616 18:59:00.563099    7849 defaults.go:174] creating security context for container wildfly
    -replicationcontrollers/wildfly
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    kind: ReplicationController
    -apiVersion: v1beta3
    -metadata:
    -  name: wildfly
    -  labels:
    -    name: wildfly
    -    context: docker-k8s-lab
    -spec:
    -  replicas: 1
    -  selector:
    -    name: wildfly-server
    -  template:
    -    metadata:
    -      labels:
    -        name: wildfly-server
    -        context: docker-k8s-lab
    -    spec:
    -      containers:
    -        - name: wildfly
    -          image: arungupta/wildfly-mysql-javaee7:k8s
    -          ports:
    -            - containerPort: 8080
    -              hostPort: 8080
    -
    -
    -
  2. -
  3. -

    Verify WildFly replication controller using ``docker-k8s-lab'' label as:

    -
    -
    -
    > ./cluster/kubectl.sh get rc -l context=docker-k8s-lab
    -CONTROLLER   CONTAINER(S)   IMAGE(S)                              SELECTOR              REPLICAS
    -mysql        mysql          mysql:latest                          name=mysql            1
    -wildfly      wildfly        arungupta/wildfly-mysql-javaee7:k8s   name=wildfly-server   1
    -
    -
    -
  4. -
  5. -

    Check the status of WildFly pod as:

    -
    -
    -
    > ./cluster/kubectl.sh get pod -l context=docker-k8s-lab
    -POD             IP        CONTAINER(S)   IMAGE(S)                              HOST          LABELS                                       STATUS    CREATED      MESSAGE
    -mysql-7lq67                                                                    10.245.1.3/   context=docker-k8s-lab,name=mysql            Pending   3 minutes
    -                          mysql          mysql:latest
    -wildfly-o0nw6                                                                  10.245.1.3/   context=docker-k8s-lab,name=wildfly-server   Pending   45 seconds
    -                          wildfly        arungupta/wildfly-mysql-javaee7:k8s
    -
    -
    -
  6. -
-
-
-

Make sure the status of both WildFly and MySQL pod is changed to ``running''. It will look like:

-
-
-
-
> ./cluster/kubectl.sh get pod -l context=docker-k8s-lab
-POD             IP            CONTAINER(S)   IMAGE(S)                              HOST                    LABELS                                       STATUS    CREATED      MESSAGE
-mysql-7lq67     172.17.0.9                                                         10.245.1.3/10.245.1.3   context=docker-k8s-lab,name=mysql            Running   14 minutes
-                              mysql          mysql:latest                                                                                               Running   10 minutes
-wildfly-o0nw6   172.17.0.10                                                        10.245.1.3/10.245.1.3   context=docker-k8s-lab,name=wildfly-server   Running   11 minutes
-                              wildfly        arungupta/wildfly-mysql-javaee7:k8s                                                                        Running   26 seconds
-
-
-
- - - - - -
-
Note
-
-Takes a while for all the pods to start. It took ~25 minutes on a 16 GB, i7 Mac OS X. -
-
-
-
-
-

14.4. Access Java EE Application

- -
-
-

14.5. Self-healing Pods

-
-
    -
  1. -

    Delete the WildFly pod

    -
  2. -
  3. -

    Wait for k8s to restart the pod because of RC

    -
  4. -
-
-
-
-

14.6. Application Logs

-
-
    -
  1. -

    Login to Minion-1 VM:

    -
    -
    -
    > vagrant ssh minion-1
    -Last login: Fri Jun  5 23:01:36 2015 from 10.0.2.2
    -[vagrant@kubernetes-minion-1 ~]$
    -
    -
    -
  2. -
  3. -

    Log in as root:

    -
    -
    -
    [vagrant@kubernetes-minion-1 ~]$ su -
    -Password:
    -[root@kubernetes-minion-1 ~]#
    -
    -
    -
    -

    Default root password for VM images created by Vagrant is ``vagrant''.

    -
    -
  4. -
  5. -

    See the list of Docker containers running on this VM:

    -
    -
    -
    docker ps
    -
    -
    -
  6. -
  7. -

    View WildFly log as:

    -
    -
    -
    docker logs $(docker ps | grep arungupta/wildfly | awk '{print $1}')
    -
    -
    -
  8. -
  9. -

    View MySQL log as:

    -
    -
    -
    docker logs <CID>
    -
    -
    -
  10. -
-
-
-
-

14.7. Delete Kubernetes Resources

-
-

Individual resources (service, replication controller, or pod) can be deleted by using delete command instead of create command. Alternatively, all services and replication controllers can be deleted using a label as:

-
-
-
-
kubectl delete -l se,po context=docker-k8s-lab
-
-
-
-
-

14.8. Stop Kubernetes Cluster

-
-
-
> ./cluster/kube-down.sh
-Bringing down cluster using provider: vagrant
-==> minion-1: Forcing shutdown of VM...
-==> minion-1: Destroying VM and associated drives...
-==> master: Forcing shutdown of VM...
-==> master: Destroying VM and associated drives...
-Done
-
-
-
-
-

14.9. View Logs

- -
-
-

14.10. Debug Kubernetes Master (OPTIONAL)

-
-
    -
  1. -

    Log in to the master as:

    -
    -
    -
    > vagrant ssh master
    -Last login: Thu Jun  4 19:30:04 2015 from 10.0.2.2
    -[vagrant@kubernetes-master ~]$
    -
    -
    -
  2. -
  3. -

    Log in as root:

    -
    -
    -
    [vagrant@kubernetes-master ~]$ su -
    -Password:
    -Last login: Thu Jun  4 19:25:41 UTC 2015
    -[root@kubernetes-master ~]
    -
    -
    -
    -

    Default root password for VM images created by Vagrant is ``vagrant''.

    -
    -
  4. -
  5. -

    Check the containers running on master:

    -
    -
    -
    CONTAINER ID        IMAGE                                                                               COMMAND                CREATED             STATUS              PORTS               NAMES
    -2b92c80630d5        gcr.io/google_containers/etcd:2.0.9                                                 "/usr/local/bin/etcd   5 hours ago         Up 5 hours                              k8s_etcd-container.ec4297e5_etcd-server-kubernetes-master_default_3595ac402f3a17c29dab95f3e0f64c76_56fa3dce
    -64c375f8030b        gcr.io/google_containers/kube-apiserver:465b93ab80b30057f9c2ef12f30450c3            "/bin/sh -c '/usr/lo   5 hours ago         Up 5 hours                              k8s_kube-apiserver.f4e485e1_kube-apiserver-kubernetes-master_default_c6b19d563bdbcfb0af80b57377ee905c_2f16c239
    -d7d9d40bd479        gcr.io/google_containers/kube-controller-manager:572696d43ca87cd1fe0c774bac3a5f4b   "/bin/sh -c '/usr/lo   5 hours ago         Up 5 hours                              k8s_kube-controller-manager.70259e73_kube-controller-manager-kubernetes-master_default_8f8db766ebc90a00a99244c362284cf1_6eff7640
    -13251c4df211        gcr.io/google_containers/kube-scheduler:d1f640dfb379f64daf3ae44286014821            "/bin/sh -c '/usr/lo   5 hours ago         Up 5 hours                              k8s_kube-scheduler.f53b6329_kube-scheduler-kubernetes-master_default_1f3b1657f7f1af67ce9f929d78c64695_de632a80
    -b1809bdabd9c        gcr.io/google_containers/pause:0.8.0                                                "/pause"               5 hours ago         Up 5 hours                              k8s_POD.e4cc795_kube-apiserver-kubernetes-master_default_c6b19d563bdbcfb0af80b57377ee905c_767dadb1
    -280baf845b00        gcr.io/google_containers/pause:0.8.0                                                "/pause"               5 hours ago         Up 5 hours                              k8s_POD.e4cc795_kube-scheduler-kubernetes-master_default_1f3b1657f7f1af67ce9f929d78c64695_52a4ca74
    -615a314a35bf        gcr.io/google_containers/pause:0.8.0                                                "/pause"               5 hours ago         Up 5 hours                              k8s_POD.e4cc795_kube-controller-manager-kubernetes-master_default_8f8db766ebc90a00a99244c362284cf1_97cc1739
    -7a554eea05f3        gcr.io/google_containers/pause:0.8.0                                                "/pause"               5 hours ago         Up 5 hours                              k8s_POD.e4cc795_etcd-server-kubernetes-master_default_3595ac402f3a17c29dab95f3e0f64c76_593b9807
    -
    -
    -
  6. -
-
-
-
-
-
-

15. Common Docker Commands

-
-
-

Here is the list of commonly used Docker commands:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PurposeCommand

Build an image

docker build --rm=true .

Install an image

docker pull ${IMAGE}

List of installed images

docker images

List of installed images (detailed listing)

docker images --no-trunc

Remove an image

docker rmi ${IMAGE_ID}

Remove all untagged images

docker rmi $(docker images | grep “^” | awk “{print $3}”)

Remove all images

docker rm $(docker ps -aq)

Run a container

docker run

List containers

docker ps

Stop a container

docker stop ${CID}

Stop all running containers

docker stop docker ps -q

Find IP address of the container

docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID}

Attach to a container

docker attach ${CID}

Remove a container

docker rm ${CID}

Remove all containers

docker rm $(docker ps -aq)

Get container id for an image by regular expression

docker ps | grep arungupta/wildfly | awk '{print $1}'

-
-
-
-

16. References

-
-
-
    -
  1. -

    JBoss and Docker: http://www.jboss.org/docker/

    -
  2. -
-
-
-
-
- - - \ No newline at end of file diff --git a/instructor/dockerfiles/lab-httpd-server/run-apache.sh b/instructor/dockerfiles/lab-httpd-server/run-apache.sh deleted file mode 100644 index 8e6a352..0000000 --- a/instructor/dockerfiles/lab-httpd-server/run-apache.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# Make sure we're not confused by old, incompletely-shutdown httpd -# context after restarting the container. httpd won't start correctly -# if it thinks it is already running. -rm -rf /run/httpd/* /tmp/httpd* - -exec /usr/sbin/apachectl -D FOREGROUND \ No newline at end of file diff --git a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/Dockerfile b/instructor/dockerfiles/ticketmonster-pgsql-wildfly/Dockerfile deleted file mode 100644 index 6ab96cb..0000000 --- a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# Use latest jboss/wildfly -FROM jboss/wildfly - -MAINTAINER "Rafael Benevides" - -#Create admin user -RUN /opt/jboss/wildfly/bin/add-user.sh -u admin -p docker#admin --silent - -# Add customization folder -COPY customization /opt/jboss/wildfly/customization/ - -USER root - -# Run customization scripts as root -RUN chmod +x /opt/jboss/wildfly/customization/execute.sh -RUN /opt/jboss/wildfly/customization/execute.sh standalone standalone-ha.xml - -ADD ticket-monster.war /opt/jboss/wildfly/standalone/deployments/ - -# Fix for Error: Could not rename /opt/jboss/wildfly/standalone/configuration/standalone_xml_history/current -RUN rm -rf /opt/jboss/wildfly/standalone/configuration/standalone_xml_history - -RUN chown -R jboss:jboss /opt/jboss/wildfly/ - -USER jboss - -# Expose the ports we're interested in -EXPOSE 8080 9990 - -# Set the default command to run on boot -# This will boot WildFly in the standalone mode and bind to external interface and enable HA -CMD /opt/jboss/wildfly/bin/standalone.sh -b `hostname -i` -bmanagement `hostname -i` -c standalone-ha.xml - diff --git a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/commands.cli b/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/commands.cli deleted file mode 100644 index ee35d77..0000000 --- a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/commands.cli +++ /dev/null @@ -1,18 +0,0 @@ -# Mark the commands below to be run as a batch -batch - -# Configure mod_cluster to no use tcp advertisement -/subsystem=modcluster/mod-cluster-config=configuration:write-attribute(name=advertise,value=false) -/subsystem=modcluster/mod-cluster-config=configuration:write-attribute(name=proxy-list,value=${modcluster.host:modcluster}:80) - -# Add Postgres JDBC Driver as a module -module add --name=org.postgresql --resources=/opt/jboss/wildfly/customization/postgresql-9.4-1201.jdbc41.jar --dependencies=javax.api,javax.transaction.api - -#Add PostgreSQL JDBC Driver -/subsystem=datasources/jdbc-driver=postgres:add(driver-name=postgres, driver-module-name=org.postgresql, driver-class-name=org.postgresql.Driver) - -#Add Datasource -data-source add --name=TicketMonsterPostgreSQLDS --jndi-name=java:jboss/datasources/TicketMonsterPostgreSQLDS --driver-name=postgres --connection-url=jdbc:postgresql://${postgres.host:db}:5432/ticketmonster --user-name=ticketmonster --password=ticketmonster-docker --valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker --exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter --validate-on-match=true --background-validation=true - -#Execute the batch -run-batch \ No newline at end of file diff --git a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/execute.sh b/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/execute.sh deleted file mode 100755 index cea5530..0000000 --- a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/execute.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Usage: execute.sh [WildFly mode] [configuration file] -# -# The default mode is 'standalone' and default configuration is based on the -# mode. It can be 'standalone.xml' or 'domain.xml'. - -JBOSS_HOME=/opt/jboss/wildfly -JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh -JBOSS_MODE=${1:-"standalone"} -JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"} - -function wait_for_server() { - until `$JBOSS_CLI -c "ls /deployment" &> /dev/null`; do - sleep 1 - done -} - -echo "=> Starting WildFly server" -$JBOSS_HOME/bin/$JBOSS_MODE.sh -c $JBOSS_CONFIG -Dmodcluster.host=127.0.0.1 > /dev/null & - -echo "=> Waiting for the server to boot" -wait_for_server - -echo "=> Executing the commands" -$JBOSS_CLI -c --file=`dirname "$0"`/commands.cli - -echo "=> Shutting down WildFly" -if [ "$JBOSS_MODE" = "standalone" ]; then - $JBOSS_CLI -c ":shutdown" -else - $JBOSS_CLI -c "/host=*:shutdown" -fi - diff --git a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/postgresql-9.4-1201.jdbc41.jar b/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/postgresql-9.4-1201.jdbc41.jar deleted file mode 100644 index a3f1959..0000000 Binary files a/instructor/dockerfiles/ticketmonster-pgsql-wildfly/customization/postgresql-9.4-1201.jdbc41.jar and /dev/null differ diff --git a/instructor/extra.adoc b/instructor/extra.adoc deleted file mode 100644 index f4905e4..0000000 --- a/instructor/extra.adoc +++ /dev/null @@ -1,34 +0,0 @@ -# Environment maintenance - -This are some instructions to keep the instructor environment - - -## Uptating the attendees instructions served by the instructor httpd server - -The instructor webserver [http://localhost:8082/] provides the link:https://github.com/javaee-samples/docker-java/blob/master/docker-java-lab.adoc[attendes instructions] in the HTML format. - -To update the HTML, have http://asciidoctor.org/ installed and run the following command: - -[source, text] ----- -asciidoctor ../docker-java-lab.adoc -a data-uri -a numbered -a experimental -a source-highlighter=coderay -a imagesdir=images -o dockerfiles/lab-httpd-server/index.html ----- - -After that, you will need to build the services again running - -[source, text] ----- -docker-compose build ----- - - -## Backing up Nexus data container to a file - -If you need to update the nexusbackup.tar file, run the following command: - -[source, text] ----- -docker run --rm --volumes-from nexusdata -v $(pwd):/backup ubuntu tar cvf /backup/nexusbackup.tar /sonatype-work ----- - -This will compress the contents of /sonatype-work folder from the nexusdata container in to a file called nexusbackup.tar \ No newline at end of file diff --git a/instructor/images/gitlab-default-output.png b/instructor/images/gitlab-default-output.png deleted file mode 100644 index 5935148..0000000 Binary files a/instructor/images/gitlab-default-output.png and /dev/null differ diff --git a/instructor/images/nexus-default-output.png b/instructor/images/nexus-default-output.png deleted file mode 100644 index 96275cb..0000000 Binary files a/instructor/images/nexus-default-output.png and /dev/null differ diff --git a/instructor/images/registry-default-output.png b/instructor/images/registry-default-output.png deleted file mode 100644 index 8d94ee4..0000000 Binary files a/instructor/images/registry-default-output.png and /dev/null differ diff --git a/instructor/images/webserver-default-output.png b/instructor/images/webserver-default-output.png deleted file mode 100644 index cc16491..0000000 Binary files a/instructor/images/webserver-default-output.png and /dev/null differ diff --git a/instructor/nexusbackup.tar b/instructor/nexusbackup.tar deleted file mode 100644 index ff0baae..0000000 Binary files a/instructor/nexusbackup.tar and /dev/null differ diff --git a/instructor/push-images-to-registry.sh b/instructor/push-images-to-registry.sh deleted file mode 100755 index d53600e..0000000 --- a/instructor/push-images-to-registry.sh +++ /dev/null @@ -1,61 +0,0 @@ -# Wildfly -docker pull jboss/wildfly -docker tag jboss/wildfly localhost:5000/wildfly -docker push localhost:5000/wildfly - -# Managed WildFly -docker pull arungupta/wildfly-management -docker tag arungupta/wildfly-management localhost:5000/wildfly-management -docker push localhost:5000/wildfly-management - -# Ticket-monster+PGSQ+WildFly -docker tag instructor/ticketmonster-pgsql-wildfly localhost:5000/ticketmonster-pgsql-wildfly -docker push localhost:5000/ticketmonster-pgsql-wildfly - -# Postgres -docker pull postgres -docker tag postgres localhost:5000/postgres -docker push localhost:5000/postgres - -# Modcluster -docker pull goldmann/mod_cluster -docker tag goldmann/mod_cluster localhost:5000/mod_cluster -docker push localhost:5000/mod_cluster - -#Java EE 7 hol -docker pull arungupta/javaee7-hol -docker tag arungupta/javaee7-hol localhost:5000/javaee7-hol -docker push localhost:5000/javaee7-hol - -# MySQL -docker pull mysql:latest -docker tag mysql localhost:5000/mysql -docker push localhost:5000/mysql - -# WildFly MySQL -docker pull arungupta/wildfly-mysql-javaee7 -docker tag arungupta/wildfly-mysql-javaee7 localhost:5000/wildfly-mysql-javaee7 -docker push localhost:5000/wildfly-mysql-javaee7 - -# Docker Swarm -docker pull swarm -docker tag swarm localhost:5000/swarm -docker push localhost:5000/swarm - -#OpenShift Origin -#docker pull openshift/origin -#docker tag openshift/origin localhost:5000/openshift-origin -#docker push localhost:5000/openshift-origin -#docker pull openshift/origin-docker-registry -#docker tag openshift/origin-docker-registry localhost:5000/openshift-origin-docker-registry -#docker push localhost:5000/openshift-origin-docker-registry -#docker pull openshift/origin-sti-builder -#docker tag openshift/origin-sti-builder localhost:5000/openshift-origin-sti-builder -#docker push localhost:5000/openshift-origin-sti-builder -#docker pull openshift/origin-deployer -#docker tag openshift/origin-deployer localhost:5000/openshift-origin-deployer -#docker push localhost:5000/openshift-origin-deployer -#docker pull arungupta/wildfly-mysql-javaee7:k8s -#docker tag arungupta/wildfly-mysql-javaee7:k8s localhost:5000/wildfly-mysql-javaee7:k8s -#docker push localhost:5000/wildfly-mysql-javaee7:k8s - diff --git a/instructor/readme.adoc b/instructor/readme.adoc deleted file mode 100644 index b11490d..0000000 --- a/instructor/readme.adoc +++ /dev/null @@ -1,335 +0,0 @@ -= Docker for Java Developers - Instructor Setup -:toc: -:toc-placement!: - -This folder contains instructions to setup an Instructor environment. - -IMPORTANT: Make sure to run these instructions a day prior to the lab. You need a good Internet connection as several files and Docker images need to be downloaded. Plan for at least 60 minutes. - -Instructor needs: - -. Docker Registry server -. Boot2docker served by a local HTTP Server -. Nexus Proxy - -NOTE: All instructions are to be run from the `instructor` directory. - -## Prerequisites - -### Hardware - -. CPU -.. Mac: X64 (i5 or superior) -.. Linux / Windows: x64 (i5 and comparable) - -. Memory: At least 8 GB, 16 GB is preferred - -### Software - -. Operating System -.. Mac OS X (10.8 or later), Windows 7 (SP1), Fedora (21 or later) -. http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html[Oracle JDK 8u45] -. http://maven.apache.org/download.cgi[Maven 3.0 or later] -. https://www.virtualbox.org/[Oracle Virtualbox], include install folder to your PATH. -. https://git-scm.com/book/en/v2/Getting-Started-Installing-Git[Git Client] -. Check out https://github.com/javaee-samples/docker-java/ git repository. -. Webbrowser -.. https://www.google.com/chrome/browser/desktop/[Chrome] -.. link:http://www.getfirefox.com[Firefox] - - -## Install Docker Client -Docker Client allows to interact with Docker Host. Download and install by just copying and renaming it accordingly. - -[source, text] ----- -#Linux (Fedora only) -yum install docker-io - -# MacOS / Linux (other distros) -curl -L https://get.docker.com/builds/`uname -s`/x86_64/docker-latest > /usr/local/bin/docker -chmod +x /usr/local/bin/docker - -#Windows -Download: -https://get.docker.com/builds/Windows/x86_64/docker-latest.exe -https://get.docker.com/builds/Windows/i386/docker-latest.exe -And save to c:\Users\\docker\docker.exe ----- - -## Install Docker Compose -Docker Compose simplifies instructor's setup. The link:https://github.com/arun-gupta/docker-java/blob/master/instructor/docker-compose.yml[docker-compose.yml] contains all the instructions for the tool to setup and start the infrastructure. - -Learn more about the tool on link:https://docs.docker.com/compose/[Docker Compose Website]. - - -[source, text] ----- -# Linux / MacOS -curl -L https://github.com/docker/compose/releases/download/1.3.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose -chmod +x /usr/local/bin/docker-compose ----- - -Docker Compose is not natively supported on Windows and thus requires a workaround as specfied at http://blog.eisele.net/2015/06/docker-compose-on-windows-with-python.html. -You need to install Babun and Python to get further from here on. - -## Install and Configure Docker Machine -Install the Docker machine client for your environment: https://github.com/docker/machine/releases/[latest releases] - -[source, text] ----- -# MacOS -curl -L https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_darwin-amd64 > /usr/local/bin/docker-machine -chmod +x /usr/local/bin/docker-machine - -# Linux -curl -L https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_linux-amd64 > /usr/local/bin/docker-machine -chmod +x /usr/local/bin/docker-machine - -# Windows -Download: -https://github.com/docker/machine/releases/download/v0.3.0/docker-machine_windows-amd64.exe -And save to c:\Users\\docker\docker-machine.exe ----- - -For Windows, make sure to add `c:\Users\\docker` to your `%PATH%` variable. This was already done for Linux / MacOs when you downloaded `docker-machine` script to `/usr/local/bin/docker-machine`. - -If you're executing commands in the Babun bash from here on, make sure to keep in mind, that the Path variable is set in Linux/Unix style: -`PATH=$PATH\:/d/Program\ Files\ \(x86\)/docker ; export PATH`. You have to escape all special characters with a backslash. - -### Set up DNS - -There is no in-built support for DNS and so this needs to be configured. Currently this works only on Mac and Linux, and need to be fixed for Windows https://github.com/javaee-samples/docker-java/issues/61[#61]. - -. Edit `/etc/hosts` (Mac OS / Linux) -+ -[source, text] ----- - classroom.example.com ----- -+ -IMPORTANT: is the IP of your public interface eg. `en0, eth0`. -+ - -. Install a simple dns server such as `dnsmasq` as: -+ -[source, text] ----- -brew install dnsmasq ----- -+ -to see the output as: -+ -[source, text] ----- -> brew install dnsmasq -==> Downloading http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.72.tar.gz -######################################################################## 100.0% -==> make install PREFIX=/usr/local/Cellar/dnsmasq/2.72 -==> Caveats -To configure dnsmasq, copy the example configuration to /usr/local/etc/dnsmasq.conf -and edit to taste. - - cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf - -To have launchd start dnsmasq at startup: - sudo cp -fv /usr/local/opt/dnsmasq/*.plist /Library/LaunchDaemons - sudo chown root /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist -Then to load dnsmasq now: - sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist -==> Summary -🍺 /usr/local/Cellar/dnsmasq/2.72: 7 files, 492K, built in 28 seconds - -You may need to restart Dnsmasq to get it to recognise this change: - -sudo launchctl stop homebrew.mxcl.dnsmasq -sudo launchctl start homebrew.mxcl.dnsmasq ----- -+ -This can be done on Linux as: -+ -[source, text] ----- -sudo yum -­y install dnsmasq ----- -+ -. Edit `/etc/resolv.conf` (Mac OS / Linux) -+ -[source, text] ----- -nameserver ----- - -. Make sure that dnsmasq starts automatically follow the instructions from brew or yum. - - -### Create Machine - -. Creates instructor host which will run the complete infrastructure. -+ -[source, text] ----- -docker-machine create --driver=virtualbox --virtualbox-memory=4096 --virtualbox-boot2docker-url=https://github.com/boot2docker/boot2docker/releases/download/v1.7.0/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 instructor-machine ----- - -+ -. Configure Docker client to run the commands on this newly created machine as: -+ -[source, text] ----- -eval "$(docker-machine env instructor-machine)" ----- - -+ -IMPORTANT: If you change your network, you may need to restart your docker machine: -[source, text] ----- -docker-machine restart instructor-machine ----- - - -### Virtual Box Configuration - -Expose the Virtual Box ports to other computer in the LAN - -VirtualBox will run docker container inside the newly create host called 'instructor-machine'. We need now to expose the ports used in this lab to the world. - -[source, text] ----- -#Open Registry Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port5000,tcp,,5000,,5000"; -#Open Nexus Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8081,tcp,,8081,,8081"; -#Open HTTP Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8082,tcp,,8082,,8082"; -#Open gitlab ports -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10022,tcp,,10022,,10022"; -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10080,tcp,,10080,,10080"; ----- - -This is available as a script in https://github.com/javaee-samples/docker-java/blob/master/instructor/virtualbox-ports.sh. -A Windows version in https://github.com/javaee-samples/docker-java/blob/master/instructor/virtualbox-ports.bat - -## Container with Nexus Dependencies - -Create a container with Nexus dependencies. - -We want to provide an option to run this lab without any Internet access. So, the instructor machine will contain everything that the attendees will need to run this lab. -[source, text] ----- -docker run --name="nexusdata" -v $(pwd):/backup sonatype/nexus:oss bash -c "tar xvf /backup/nexusbackup.tar -C /" ----- - -NOTE: Running Windows, make sure to copy the `nexusbackup.tar` to the following folder `c:/Users//docker-hol` and make sure to update the docker run command accordingly. -The folder permissions in Windows don't allow for a location of your choice. - -This will download the Nexus image on Docker host and populate it with the Nexus dependencies. - -## Download JBoss Developer Studio 9.0 Nightly - -Download https://devstudio.redhat.com/9.0/snapshots/builds/devstudio.product_master/2015-06-09_06-24-34-B3346/installer/[JBoss Developer Studio 9.0 - Nightly - 482MB - JAR File] and place it inside `dockerfiles/lab-httpd-server/downloads` folder. - -## Start the Instructor Environment - -Use the following compose command to startup the complete environment at once. - -NOTE: This command should take some time to execute as it will download the required Docker images. - -[source, text] ----- -docker-compose up -d ----- - -The status of different servers can be verified as: - -[source, text] ----- -instructor> docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -7b847ca4554e registry:2.0 "registry cmd/regist 45 seconds ago Up 45 seconds 0.0.0.0:5000->5000/tcp instructor_dockerregistry_1 -3704d3205eac sameersbn/gitlab:7.10.4 "/app/init app:start About a minute ago Up About a minute 443/tcp, 0.0.0.0:10022->22/tcp, 0.0.0.0:10080->80/tcp instructor_gitlab_1 -66ac375ecd8d sameersbn/postgresql:9.4 "/start" 2 minutes ago Up 2 minutes 5432/tcp instructor_postgresqlgitlab_1 -b4a36e701386 sonatype/nexus:oss "/bin/sh -c 'java 4 minutes ago Up 4 minutes 0.0.0.0:8081->8081/tcp instructor_nexus_1 -5986b380732c sameersbn/redis:latest "/start" 4 minutes ago Up 4 minutes 6379/tcp instructor_redisgitlab_1 -a041b58ceff1 instructor_httpserver:latest "/run-apache.sh" 5 minutes ago Up 5 minutes 0.0.0.0:8082->80/tcp instructor_httpserver_1 ----- - -Test if the servers are running: - -. Docker Registry [http://localhost:5000/] -+ -image::images/registry-default-output.png[] -+ -. Nexus Console [http://localhost:8081/content/groups/public/] -+ -image::images/nexus-default-output.png[] -+ -. Apache Webserver [http://localhost:8082/] -+ -image::images/webserver-default-output.png[] -+ -. Gitlab server [http://localhost:10080/] -+ -image::images/gitlab-default-output.png[] - - -## Populate Gitlab with Ticket Monster Source Code -In order to allow a complete offline experience, we also host our own git repository for the demo application on the instructor machine. - -NOTE: Gitlab must have completed his startup. It usually takes 3 minutes to do so. - -Execute: - -[source,text] ----- -docker exec instructor_gitlab_1 bash -c "cd /home/git/data/repositories/root; git clone --bare https://github.com/rafabene/ticket-monster.git; chown git:git -R /home/git/data/repositories; cd /home/git/gitlab; sudo -u git -H bundle exec rake -v gitlab:import:repos RAILS_ENV=production" ----- - -This will show the output as: - -[source, text] ----- -Cloning into bare repository 'ticket-monster.git'... -Processing root/ticket-monster.git - * Created ticket-monster (root/ticket-monster.git) -Done! ----- - -## Build TicketMonster from Source Code - -1. Clone TicketMonster from the existing gitlab container - - git clone -b WildFly-docker-test http://root:dockeradmin@localhost:10080/root/ticket-monster.git - -2. Build TicketMonster - - mvn -s settings.xml -f ticket-monster/demo/pom.xml -Ppostgresql clean package - -3. Copy TicketMonster war to the Docker ticketmonster-pgsql-widlfly image folder - - cp ticket-monster/demo/target/ticket-monster.war dockerfiles/ticketmonster-pgsql-wildfly/ - -## Build Images - -Build ``managed-widlfly'' and ``ticketmonster-pgsql-widlfly'' images - -[source, text] ----- -docker build -t "instructor/wildfly-management" dockerfiles/wildfly-management/ -docker build -t "instructor/ticketmonster-pgsql-wildfly" dockerfiles/ticketmonster-pgsql-wildfly/ ----- - -This is available as a script in https://github.com/javaee-samples/docker-java/blob/master/instructor/buid-images.sh - -## Push Images to Registry - -Push the required images to the local registry by executing the script `push-images-to-registry.sh`. - -## More information - -If you need some extra information like: - -- Updating the attendees instructions served by the instructor httpd server -- Backing up Nexus data container to a file - -Please, check the link:extra.adoc[extra instructions]. diff --git a/instructor/settings.xml b/instructor/settings.xml deleted file mode 100644 index 85097d3..0000000 --- a/instructor/settings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - instructor-repository - - - instructor-nexus-repository - http://localhost:8081/content/groups/public/ - - true - - - false - - - - - - instructor-plugin-repository - http://localhost:8081/content/groups/public/ - - true - - - false - - - - - - - - - - instructor-repository - - - diff --git a/instructor/virtualbox-ports.bat b/instructor/virtualbox-ports.bat deleted file mode 100644 index 61fd55d..0000000 --- a/instructor/virtualbox-ports.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -echo Open Registry Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port5000,tcp,,5000,,5000"; -echo Open Nexus Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8081,tcp,,8081,,8081"; -echo Open HTTP Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8082,tcp,,8082,,8082"; -echo Open gitlab ports -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10022,tcp,,10022,,10022"; -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10080,tcp,,10080,,10080"; - diff --git a/instructor/virtualbox-ports.sh b/instructor/virtualbox-ports.sh deleted file mode 100755 index 4b55260..0000000 --- a/instructor/virtualbox-ports.sh +++ /dev/null @@ -1,10 +0,0 @@ -#Open Registry Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port5000,tcp,,5000,,5000"; -#Open Nexus Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8081,tcp,,8081,,8081"; -#Open HTTP Server port -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port8082,tcp,,8082,,8082"; -#Open gitlab ports -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10022,tcp,,10022,,10022"; -VBoxManage controlvm "instructor-machine" natpf1 "tcp-port10080,tcp,,10080,,10080"; - diff --git a/managed-container-service.adoc b/managed-container-service.adoc new file mode 100644 index 0000000..55dd186 --- /dev/null +++ b/managed-container-service.adoc @@ -0,0 +1,23 @@ += Managed Container Service + +This document compares managed container services. + +. https://www.docker.com/products/docker-datacenter[Docker Data Center] or https://docs.docker.com/docker-for-aws/[Docker for AWS] / https://docs.docker.com/docker-for-azure/[Azure] +. https://cloud.google.com/container-engine/[Google Container Engine] (GCE) +. https://dcos.io/[DC/OS] +. https://azure.microsoft.com/en-us/services/container-service/[Azure Container Service] (Azure) +. https://aws.amazon.com/ecs/[Amazon Elastic Container Service] (ECS) +. https://www.openshift.org/[Red Hat OpenShift] +. https://cloud.oracle.com/container[Oracle Cloud Container Service] + +[width="100%", options="header"] +|================== +| Feature | Docker | GCE | DC/OS | Azure | ECS | OpenShift | Oracle +| Company | Docker | Google | Mesosphere | Microsoft | Amazon | Red Hat | Oracle +| Orchestration Framework | Docker Engine | Kubernetes | Apache Mesos | Kubernetes | Closed source | Kubernetes | Closed source +| Docker version | | | | | | | +| CI/CD | | | | | | | +| REST API | | | | | | | +| Console | | | | | | | +|================== + diff --git a/readme.adoc b/readme.adoc index 44cb1e8..b9c9726 100644 --- a/readme.adoc +++ b/readme.adoc @@ -1,60 +1,13 @@ -# Docker and Kubernetes for Java Developers -v1.2.x, Aug 13, 2015 -:toc: -:toc-title: Table of Dockernetes -:toclevels: 3 -:toc-placement!: -:imagesdir: ./chapters/images/ += Docker and Kubernetes for Java Developers -toc::[] +https://github.com/docker/labs/tree/master/developer-tools/java[Docker for Java developers] -include::chapters/docker-preface.adoc[] +https://github.com/arun-gupta/kubernetes-java-sample/[Kubernetes for Java developers] -include::chapters/docker-setup.adoc[] +== Software Requirements -include::chapters/docker-basics.adoc[] - -include::chapters/docker-container.adoc[] - -include::chapters/docker-javaee7.adoc[] - -include::chapters/docker-container-linking.adoc[] - -include::chapters/docker-deployment-options.adoc[] - -//// -include::chapters/docker-ticket-monster.adoc[] -//// - -include::chapters/docker-maven.adoc[] - -include::chapters/docker-eclipse.adoc[] - -//// -include::chapters/docker-netbeans.adoc[] - -include::chapters/docker-intellij.adoc[] -//// - -include::chapters/docker-testing.adoc[] - -include::chapters/docker-compose.adoc[] - - -//// -include::chapters/docker-mod-cluster.adoc[] -//// - -include::chapters/docker-swarm.adoc[] - -include::chapters/docker-kubernetes.adoc[] - -//// -include::chapters/docker-continuous-delivery.adoc[] - -include::chapters/docker-openshift.adoc[] -//// - -include::chapters/docker-commands.adoc[] - -include::chapters/docker-references.adoc[] +. Docker for Java: https://github.com/docker/labs/blob/master/developer-tools/java/chapters/ch01-setup.adoc +. Kubernetes for Java +.. Install: https://github.com/arun-gupta/kubernetes-java-sample/blob/master/workshop.adoc#initial-setup +.. An Amazon Web Services account +.. Clone: https://github.com/arun-gupta/kubernetes-java-sample diff --git a/readme.html b/readme.html deleted file mode 100644 index 789306b..0000000 --- a/readme.html +++ /dev/null @@ -1,4671 +0,0 @@ - - - - - - - - -Docker and Kubernetes for Java Developers - - - - - - -
-
-
-
-
Table of Dockernetes
- -
-
-
-
-

1. Preface

-
-
-

Containers are enabling developers to package their applications (and underlying dependencies) in new ways that are portable and work consistently everywhere? On your machine, in production, in your data center, and in the cloud. And Docker has become the de facto standard for those portable containers in the cloud.

-
-
-

Docker is the developer-friendly Linux container technology that enables creation of your stack: OS, JVM, app server, app, and all your custom configuration. So with all it offers, how comfortable are you and your team taking Docker from development to production? Are you hearing developers say, “But it works on my machine!” when code breaks in production?

-
-
-

This lab offers developers an intro-level, hands-on session with Docker, from installation, to exploring Docker Hub, to crafting their own images, to adding Java apps and running custom containers. It will also explain how to use Swarm to orchesorchestrate these containers together. This is a BYOL (bring your own laptop) session, so bring your Windows, OSX, or Linux laptop and be ready to dig into a tool that promises to be at the forefront of our industry for some time to come.

-
-
- - - - - -
-
Note
-
-Latest content of this lab is always at https://github.com/javaee-samples/docker-java -
-
-
-
-
-

2. Setup Environments

-
-
-

This section describes what, how, and where to install the software needed for this lab. This lab is designed for a BYOL (Brying Your Own Laptop) style hands-on-lab.

-
-
-

2.1. Hardware

-
-
    -
  1. -

    Operating System: Mac OS X (10.8 or later), Windows 7 (SP1), Fedora (21 or later)

    -
  2. -
  3. -

    Memory: At least 4 GB+, preferred 8 GB

    -
  4. -
-
-
-
-

2.2. Software

-
-
    -
  1. -

    Java: Oracle JDK 8u45

    -
  2. -
  3. -

    Web Browser

    -
    -
      -
    1. -

      Chrome

      -
    2. -
    3. -

      Firefox

      -
    4. -
    -
    -
  4. -
-
-
-
-

2.3. Git Client

- -
-
-

2.4. Maven

-
-
    -
  1. -

    Download Apache Maven from https://maven.apache.org/download.cgi.

    -
  2. -
  3. -

    Unzip to a directory of your choice and add it to the PATH.

    -
  4. -
-
-
-
-

2.5. VirtualBox

-
-

Docker currently runs natively on Linux. It can be configured to run in a virtual machine on Mac or Windows. This is why Virtualbox is a requirement for Mac or Windows.

-
-
-

Downloads are available from https://www.virtualbox.org/.

-
-
-

Virtual Box 5.0.0 does not allow Kubernetes cluster to be started: https://github.com/kubernetes/kubernetes/issues/12614. Make sure to download VirtualBox 4.3.30[https://www.virtualbox.org/wiki/Download_Old_Builds_4_3].

-
-
- - - - - -
-
Warning
-
-
-

Linux Users

-
-
-
    -
  1. -

    Have your kernel updated

    -
  2. -
  3. -

    Users should have the GNU compiler, build and header files for your current Linux kernel

    -
  4. -
  5. -

    Create a /usr/src/linux link to the current kernel source

    -
  6. -
-
-
-
-
-
-

2.6. Vagrant

-
-

Download Vagrant from https://www.vagrantup.com/downloads.html and install.

-
-
-
-

2.7. Docker Machine

-
-

Docker Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.

-
-
-
-
# Mac
-curl -L https://github.com/docker/machine/releases/download/v0.4.0/docker-machine_darwin-amd64 > /usr/local/bin/docker-machine
-chmod +x /usr/local/bin/docker-machine
-
-# Linux
-curl -L  https://github.com/docker/machine/releases/download/v0.4.0/docker-machine_linux-amd64 > /usr/local/bin/docker-machine
-chmod +x /usr/local/bin/docker-machine
-
-#Windows
-curl https://github.com/docker/machine/releases/download/v0.4.0/docker-machine.exe
-
-
-
-
-

2.8. Create Lab Docker Host

-
-
    -
  1. -

    Create Docker Host to be used in the lab:

    -
    -
    -
    docker-machine create --driver=virtualbox lab
    -eval "$(docker-machine env lab)"
    -
    -
    -
  2. -
  3. -

    To make it easier to start/stop the containers, an entry is added into the host mapping table of your operating system. Find out the IP address of your machine:

    -
    -
    -
    docker-machine ip lab
    -
    -
    -
    -

    This will provide the IP address associated with the Docker Machine created earlier.

    -
    -
  4. -
  5. -

    Edit /etc/hosts (Mac OS or Linux) or C:\Windows\System32\drivers\etc\hosts (Windows) and add:

    -
    -
    -
    <IP ADDRESS>  dockerhost
    -
    -
    -
  6. -
-
-
-
-

2.9. Docker Client

-
-

Docker Client is used to communicate with Docker Host.

-
-
-
-
# Mac
-curl -L https://get.docker.com/builds/Darwin/x86_64/docker-latest > /usr/local/bin/docker
-chmod +x /usr/local/bin/docker
-
-# Linux
-curl -L https://get.docker.com/builds/Linux/x86_64/docker-latest > docker-latest-linux
-chmod +x /usr/local/bin/docker
-
-# Windows
-curl -L http://test.docker.com.s3.amazonaws.com/builds/Windows/x86_64/docker-1.7.0.exe -o docker.exe
-
-
-
-
-

2.10. Kubernetes

-
-
    -
  1. -

    Download Kubernetes (1.0.1) from https://github.com/kubernetes/kubernetes/releases/download/v1.0.1/kubernetes.tar.gz.

    -
  2. -
  3. -

    Extract the archive and install it by:

    -
  4. -
-
-
-
-
export KUBERNETES_PROVIDER=vagrant
-cd kubernetes
-./cluster/kube-up.sh
-
-
-
- - - - - -
-
Note
-
-Kubernetes 1.0.1 is the only version verified to work with Virtual Box. More details at: https://github.com/kubernetes/kubernetes/issues/12614 -
-
-
-
-

2.11. WildFly

-
-
    -
  1. -

    Download WildFly 9.0 from http://download.jboss.org/wildfly/9.0.0.Final/wildfly-9.0.0.Final.zip.

    -
  2. -
  3. -

    Install it by extracting the archive.

    -
  4. -
-
-
-
-

2.12. JBoss Developer Studio 9 - Beta 2

-
-

To install JBoss Developer Studio stand-alone, complete the following steps:

-
-
-
    -
  1. -

    Download 9.0.0 Beta 2 or -Latest Nightly.

    -
  2. -
  3. -

    Start the installer as:

    -
    -
    -
    java -jar <JAR FILE NAME>
    -
    -
    -
    -

    Follow the on-screen instructions to complete the installation process.

    -
    -
  4. -
-
-
-
-

2.13. Pull Docker images

-
-
-
docker pull jboss/wildfly
-docker pull arungupta/wildfly-management
-docker pull arungupta/javaee7-hol
-docker pull mysql
-docker pull swarm
-docker pull arungupta/wildfly-mysql-javaee7
-
-
-
-
-
-
-

3. Docker Basics

-
-
-

PURPOSE: This chapter introduces the basic terminology of Docker.

-
-
-
-Docker is a platform for developers and sysadmins to develop, ship, and run applications. Docker lets you quickly assemble applications from components and eliminates the friction that can come when shipping code. Docker lets you get your code tested and deployed into production as fast as possible. -
-
-— docs.docker.com/ -
-
-
-

Docker simplifies software delivery by making it easy to build and share images that contain your application’s entire environment, or application operating system.

-
-
-

What does it mean by an application operating system ?

-
-
-

Your application typically require a specific version of operating system, application server, JDK, database server, may require to tune the configuration files, and similarly multiple other dependencies. The application may need binding to specific ports and certain amount of memory. The components and configuration together required to run your application is what is referred to as application operating system.

-
-
-

You can certainly provide an installation script that will download and install these components. Docker simplifies this process by allowing to create an image that contains your application and infrastructure together, managed as one component. These images are then used to create Docker containers which run on the container virtualization platform, provided by Docker.

-
-
-

Main Components of Docker

-
-
-

Docker has three main components:

-
-
-
    -
  1. -

    Images are build component of Docker and a read-only template of application operating system.

    -
  2. -
  3. -

    Containers are run component of Docker, and created from, images.Containers can be run, started, stopped, moved, and deleted.

    -
  4. -
  5. -

    Images are stored, shared, and managed in a registry, the distribution component of Docker. The publically available registry is known as Docker Hub (available at http://hub.docker.com).

    -
  6. -
-
-
-

In order for these three components to work together, there is Docker Daemon that runs on a host machine and does the heavy lifting of building, running, and distributing Docker containers. In addition, there is Client that is a Docker binary which accepts commands from the user and communicates back and forth with the daemon.

-
-
-
-docker architecture -
-
Figure 1. Docker architecture
-
-
-

Client communicates with Daemon, either co-located on the same host, or on a different host. It requests the Daemon to pull an image from the repository using pull command. The Daemon then downloads the image from Docker Hub, or whatever registry is configured. Multiple images can be downloaded from the registry and installed on Daemon host. Images are run using run command to create containers on demand.

-
-
-

How does a Docker Image work?

-
-
-

We’ve already seen that Docker images are read-only templates from which Docker containers are launched. Each image consists of a series of layers. Docker makes use of union file systems to combine these layers into a single image. Union file systems allow files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system.

-
-
-

One of the reasons Docker is so lightweight is because of these layers. When you change a Docker image—for example, update an application to a new version— a new layer gets built. Thus, rather than replacing the whole image or entirely rebuilding, as you may do with a virtual machine, only that layer is added or updated. Now you don’t need to distribute a whole new image, just the update, making distributing Docker images faster and simpler.

-
-
-

Every image starts from a base image, for example ubuntu, a base Ubuntu image, or fedora, a base Fedora image. You can also use images of your own as the basis for a new image, for example if you have a base Apache image you could use this as the base of all your web application images.

-
-
- - - - - -
-
Note
-
-By default, Docker obtains these base images from Docker Hub. -
-
-
-

Docker images are then built from these base images using a simple, descriptive set of steps we call instructions. Each instruction creates a new layer in our image. Instructions include actions like:

-
-
-
    -
  1. -

    Run a command

    -
  2. -
  3. -

    Add a file or directory

    -
  4. -
  5. -

    Create an environment variable

    -
  6. -
  7. -

    Run a process when launching a container

    -
  8. -
-
-
-

These instructions are stored in a file called a Dockerfile. Docker reads this Dockerfile when you request a build of an image, executes the instructions, and returns a final image.

-
-
-

How does a Container work?

-
-
-

A container consists of an operating system, user-added files, and meta-data. As we’ve seen, each container is built from an image. That image tells Docker what the container holds, what process to run when the container is launched, and a variety of other configuration data. The Docker image is read-only. When Docker runs a container from an image, it adds a read-write layer on top of the image (using a union file system as we saw earlier) in which your application can then run.

-
-
-

3.1. Docker Machine

-
-

Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.

-
-
-

Once your Docker host has been created, it then has a number of commands for managing containers:

-
-
-
    -
  1. -

    Start, stop, restart container

    -
  2. -
  3. -

    Upgrade Docker

    -
  4. -
  5. -

    Configure the Docker client to talk to a host

    -
  6. -
-
-
-

You used Docker Machine already during the attendee setup. We won’t need it too much further on. But if you need to create hosts, it’s a very handy tool to know about. From now on we’re mostly going to use the docker client.

-
-
-

Find out more about the details at the Docker Machine Website.

-
-
-

Check if docker machine is working:

-
-
-
-
docker-machine -v
-
-
-
-

It shows the output similar to the one shown below:

-
-
-
-
docker-machine version 0.3.0 (0a251fe)
-
-
-
- - - - - -
-
Note
-
-The exact version may differ based upon how recently the installation was performed. -
-
-
-
-

3.2. Docker Client

-
-

The client communicates with the demon process on your host and let’s you work with images and containers.

-
-
-

Check if your client is working using the following command:

-
-
-
-
docker -v
-
-
-
-

It shows the output similar to the following:

-
-
-
-
Docker version 1.7.0, build 0baf609
-
-
-
- - - - - -
-
Note
-
-The exact version may differ based upon how recently the installation was performed. -
-
-
-

The most important options you’ll be using frequently are:

-
-
-
    -
  1. -

    run - runs a container

    -
  2. -
  3. -

    ps- lists containers

    -
  4. -
  5. -

    stop - stops a container

    -
  6. -
  7. -

    rm - Removes a container

    -
  8. -
-
-
-

Get a full list of available commands with

-
-
-
-
docker
-
-
-
-

A more comprehensive list of commands is also available in Common Docker Commands.

-
-
-
-

3.3. Verify Docker Configuration

-
-

Check if your Docker Host is running:

-
-
-
-
docker-machine ls
-
-
-
-

You should see the output similar to:

-
-
-
-
NAME        ACTIVE   DRIVER       STATE     URL                         SWARM
-lab                  virtualbox   Running   tcp://192.168.99.101:2376
-
-
-
-

This machine is shown in “Running” state. If the machine state is stopped, start it with:

-
-
-
-
docker-machine start lab
-
-
-
-

After it is started you can find out IP address of your Docker Host with:

-
-
-
-
docker-machine ip lab
-
-
-
-

We already did this during the setup document, remember? So, this is a good chance to check, if you already added this IP to your hosts file.

-
-
-

Type:

-
-
-
-
ping dockerhost
-
-
-
-

and see if this resolves to the IP address that the docker-machine command printed out. You should see an output as:

-
-
-
-
> ping dockerhost
-PING dockerhost (192.168.99.101): 56 data bytes
-64 bytes from 192.168.99.101: icmp_seq=0 ttl=64 time=0.394 ms
-64 bytes from 192.168.99.101: icmp_seq=1 ttl=64 time=0.387 ms
-
-
-
-

If it does, you’re ready to start with the lab.

-
-
-
-
-
-

4. Run Container

-
-
-

The first step in running any application on Docker is to run a container from an image. There are plenty of images available from the official Docker registry (aka Docker Hub). To run any of them, you just have to ask the Docker Client to run it. The client will check if the image already exists on Docker Host. If it exists then it’ll run it, otherwise the host will download the image and then run it.

-
-
-

4.1. Pull Image

-
-

Let’s first check, if any images are available:

-
-
-
-
docker images
-
-
-
-

At first, this list is empty. Now, let’s get a vanilla jboss/wildfly image:

-
-
-
-
docker pull jboss/wildfly
-
-
-
-

By default, docker images are retrieved from Docker Hub.

-
-
-

You can see, that Docker is downloading the image with it’s different layers.

-
-
- - - - - -
-
Note
-
-
-

In a traditional Linux boot, the Kernel first mounts the root File System as read-only, checks its integrity, and then switches the whole rootfs volume to read-write mode. -When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. Consider each one of these file systems as a layer.

-
-
-

At first, the top read-write layer has nothing in it, but any time a process creates a file, this happens in the top layer. And if something needs to update an existing file in a lower layer, then the file gets copied to the upper layer and changes go into the copy. The version of the file on the lower layer cannot be seen by the applications anymore, but it is there, unchanged.

-
-
-

We call the union of the read-write layer and all the read-only layers a union file system.

-
-
-
-plain wildfly0 -
-
Figure 2. Docker Layers
-
-
-
-
-

In our particular case, the jboss/wildfly image extends the jboss/base-jdk:7 image which adds the OpenJDK distribution on top of the jboss/base image. -The base image is used for all JBoss community images. It provides a base layer that includes:

-
-
-
    -
  1. -

    A jboss user (uid/gid 1000) with home directory set to /opt/jboss

    -
  2. -
  3. -

    A few tools that may be useful when extending the image or installing software, like unzip.

    -
  4. -
-
-
-

The “jboss/base-jdk:7” image adds:

-
-
-
    -
  1. -

    OpenJDK 7 distribution

    -
  2. -
  3. -

    Adds a JAVA_HOME environment variable

    -
  4. -
-
-
-

When the download is done, you can list the images again and will see the following:

-
-
-
-
docker images
-REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
-jboss/wildfly       latest              e908c8c95a8b        5 days ago          581.5 MB
-
-
-
-
-

4.2. Run Container

-
-

4.2.1. Interactive Container

-
-

Run WildFly container in an interactive mode.

-
-
-
-
docker run -it jboss/wildfly
-
-
-
-

This will show the output as:

-
-
-
-
=========================================================================
-
-  JBoss Bootstrap Environment
-
-  JBOSS_HOME: /opt/jboss/wildfly
-
-  JAVA: /usr/lib/jvm/java/bin/java
-
-  JAVA_OPTS:  -server -XX:+UseCompressedOops  -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
-
-=========================================================================
-
-OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
-00:44:43,895 INFO  [org.jboss.modules] (main) JBoss Modules version 1.4.3.Final
-00:44:44,184 INFO  [org.jboss.msc] (main) JBoss MSC version 1.2.6.Final
-00:44:44,267 INFO  [org.jboss.as] (MSC service thread 1-2) WFLYSRV0049: WildFly Full 9.0.0.Final (WildFly Core 1.0.0.Final) starting
-
-. . .
-
-00:46:54,241 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
-00:46:54,243 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
-00:46:54,250 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 9.0.0.Final (WildFly Core 1.0.0.Final) started in 4256ms - Started 203 of 379 services (210 services are lazy, passive or on-demand)
-
-
-
-

This shows that the server started correctly, congratulations!

-
-
-

By default, Docker runs in the foreground. -i allows to interact with the STDIN and -t attach a TTY to the process. Switches can be combined together and used as -it.

-
-
-

Hit Ctrl+C to stop the container.

-
-
-
-

4.2.2. Detached Container

-
-

Restart the container in detached mode:

-
-
-
-
docker run -d jboss/wildfly
-972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
-
-
-
-

-d, instead of -it, runs the container in detached mode.

-
-
-

The output is the unique id assigned to the container. Check the logs as:

-
-
-
-
> docker logs 972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
-=========================================================================
-
-  JBoss Bootstrap Environment
-
-  JBOSS_HOME: /opt/jboss/wildfly
-
-. . .
-
-
-
-

We can check it by issuing the docker ps command which retrieves the images process which are running and the ports engaged by the process:

-
-
-
-
> docker ps
-CONTAINER ID        IMAGE                                 COMMAND                CREATED             STATUS              PORTS                    NAMES
-922abbb9c63a        jboss/wildfly       "/opt/jboss/wildfly/   3 seconds ago       Up 2 seconds        8080/tcp            desperate_lovelace
-
-
-
-

Also try docker ps -a to see all the containers on this machine.

-
-
-
-
-

4.3. Run Container with Default Port

-
-

Startup log of the server shows that the server is located in the /opt/jboss/wildfly. It also shows that the public interfaces are bound to the 0.0.0.0 address while the admin interfaces are bound just to localhost. This information will be useful to learn how to customize the server.

-
-
-

docker-machine ip <machine-name> gives us the Docker Host IP address and this was already added to the hosts file. So, we can give it another try by accessing: http://dockerhost:8080. However, this will not work either.

-
-
-

If you want containers to accept incoming connections, you will need to provide special options when invoking docker run. The container, we just started, can’t be accessed by our browser. We need to stop it again and restart with different options.

-
-
-
-
docker stop `docker ps | grep wildfly | awk '{print $1}'`
-
-
-
-

Restart the container as:

-
-
-
-
docker run -d -P jboss/wildfly
-
-
-
-

-P map any exposed ports inside the image to a random port on Docker host. This can be verified as:

-
-
-
-
> docker ps
-CONTAINER ID        IMAGE                                 COMMAND                CREATED             STATUS              PORTS                     NAMES
-63a69bff9c69        jboss/wildfly       "/opt/jboss/wildfly/   14 seconds ago      Up 13 seconds       0.0.0.0:32768->8080/tcp   kickass_bohr
-
-
-
-

The port mapping is shown in the PORTS column. Access the WildFly server at http://dockerhost:32768. Make sure to use the correct port number as shown in your case.

-
-
- - - - - -
-
Note
-
-Exact port number may be different in your case. -
-
-
-
-

4.4. Run Container with Specified Port

-
-

Lets stop the previously running container as:

-
-
-
-
docker stop `docker ps | grep wildfly | awk '{print $1}'`
-
-
-
-

Restart the container as:

-
-
-
-
docker run -it -p 8080:8080 jboss/wildfly
-
-
-
-

The format is -p hostPort:containerPort. This option maps container ports to host ports and allows other containers on our host to access them.

-
-
- - - - - -
-
Note
-
-
Docker Port Mapping
-
-

Port exposure and mapping are the keys to successful work with Docker. -See more about networking on the Docker website Advanced Networking

-
-
-
-
-

Now we’re ready to test http://dockerhost:8080 again. This works with the exposed port, as expected.

-
-
-
-plain wildfly1 -
-
Figure 3. Welcome WildFly
-
-
-
-

4.5. Enabling WildFly Administration

-
-

Default WildFly image exposes only port 8080 and thus is not available for administration using either the CLI or Admin Console. Lets expose the ports in different ways.

-
-
-

4.5.1. Default Port Mapping

-
-

The following command will override the default command in Docker file, start WildFly, and bind application and management port to all network interfaces.

-
-
-
-
docker run -P -d jboss/wildfly /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
-
-
-
-

Accessing WildFly Administration Console require a user in administration realm. A pre-created image, with appropriate username/password credentials, is used to start WildFly as:

-
-
-
-
docker run -P -d arungupta/wildfly-management
-
-
-
-

-P map any exposed ports inside the image to a random port on Docker host.

-
-
-

Look at the exposed ports as:

-
-
-
-
docker ps
-CONTAINER ID        IMAGE                                           COMMAND                CREATED             STATUS              PORTS                                              NAMES
-af7d6914a1f9        arungupta/wildfly-management   "/opt/jboss/wildfly/   2 seconds ago       Up 1 seconds        0.0.0.0:32770->8080/tcp, 0.0.0.0:32769->9990/tcp   happy_bardeen
-
-
-
-

Look for the host port that is mapped in the container, 32769 in this case. Access the admin console at http://dockerhost:32769.

-
-
- - - - - -
-
Note
-
-Exact port number may be different in your case. -
-
-
-

The username/password credentials are:

-
- ---- - - - - - - - - - - - - - - - - -
FieldValue

Username

admin

Password

docker#admin

-
-

This shows the admin console as:

-
-
-
-wildfly admin console -
-
Figure 4. Welcome WildFly
-
-
-
Additional Ways To Find Port Mapping
-
-

The exact mapped port can also be found as:

-
-
-
    -
  1. -

    Using docker port:

    -
    -
    -
    docker port 6f610b310a46
    -
    -
    -
    -

    to see the output as:

    -
    -
    -
    -
    0.0.0.0:32769->8080/tcp
    -0.0.0.0:32770->9990/tcp
    -
    -
    -
  2. -
  3. -

    Using docker inspect:

    -
    -
    -
    docker inspect --format='{{(index (index .NetworkSettings.Ports "9990/tcp") 0).HostPort}}' <CONTAINER ID>
    -
    -
    -
  4. -
-
-
-
-
-

4.5.2. Fixed Port Mapping

-
-

This management image can also be started with a pre-defined port mapping as:

-
-
-
-
docker run -p 8080:8080 -p 9990:9990 -d arungupta/wildfly-management
-
-
-
-

In this case, Docker port mapping will be shown as:

-
-
-
-
8080/tcp -> 0.0.0.0:8080
-9990/tcp -> 0.0.0.0:9990
-
-
-
-
-
-

4.6. Stop and Remove Container

-
-

4.6.1. Stop Container

-
-
    -
  1. -

    Stop a specific container:

    -
    -
    -
    docker stop <CONTAINER ID>
    -
    -
    -
  2. -
  3. -

    Stop all the running containers

    -
    -
    -
    docker rm $(docker stop $(docker ps -q))
    -
    -
    -
  4. -
  5. -

    Stop only the exited containers

    -
    -
    -
    docker ps -a -f "exited=-1"
    -
    -
    -
  6. -
-
-
-
-

4.6.2. Remove Container

-
-
    -
  1. -

    Remove a specific container:

    -
    -
    -
    docker rm 0bc123a8ece0
    -
    -
    -
  2. -
  3. -

    Containers meeting a regular expression

    -
    -
    -
    docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm
    -
    -
    -
  4. -
  5. -

    All running containers, without any criteria

    -
    -
    -
    docker rm $(docker ps -aq)
    -
    -
    -
  6. -
-
-
-
-
-
-
-

5. Deploy Java EE 7 Application (Pre-Built WAR)

-
-
-

Java EE 7 Movieplex is a standard multi-tier enterprise application that shows design patterns and anti-patterns for a typical Java EE 7 application.

-
-
-
-javaee7 hol -
-
Figure 5. Java EE 7 Application Architecture
-
-
-

Pull the Docker image that contains WildFly and pre-built Java EE 7 application WAR file as shown:

-
-
-
-
docker pull arungupta/javaee7-hol
-
-
-
-

The javaee7-hol Dockerfile is based on jboss/wildfly and adds the movieplex7 application as war file.

-
-
-

Run it:

-
-
-
-
docker run -it -p 8080:8080 arungupta/javaee7-hol
-
-
-
-

See the application in action at http://dockerhost:8080/movieplex7/. The output is shown:

-
-
-
-javaee7 movieplex7 -
-
Figure 6. Java EE 7 Application Output
-
-
-

This uses an in-memory database with WildFly application server as shown in the image:

-
-
-
-javaee7 hol in memory database -
-
Figure 7. In-memory Database
-
-
-

Only two changes are required to the standard jboss/wildfly image:

-
-
-
    -
  1. -

    By default, WildFly starts in Web platform. This Java EE 7 application uses some capabilities from the Full Platform and so WildFly is started in that mode instead as:

    -
    -
    -
    CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]
    -
    -
    -
  2. -
  3. -

    WAR file is copied to the standalone/deployments directory as:

    -
    -
    -
    RUN curl -L https://github.com/javaee-samples/javaee7-hol/raw/master/solution/movieplex7-1.0-SNAPSHOT.war -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war
    -
    -
    -
  4. -
-
-
-
-
-

6. Deploy Java EE 7 Application (Container Linking)

-
-
-

Deploy Java EE 7 Application (Pre-Built WAR) explained how to use an in-memory database with the application server. This gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost when the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server.

-
-
-
-javaee7 hol container linking -
-
Figure 8. Two Containers On Same Docker Host
-
-
-

This section will show how Docker Container Linking can be used to connect to a service running inside a Docker container via a network port.

-
-
-
    -
  1. -

    Start MySQL server as:

    -
    -
    -
    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
    -
    -
    -
    -

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

    -
    -
  2. -
  3. -

    Start WildFly and deploy Java EE 7 application as:

    -
    -
    -
    docker run -it --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
    -
    -
    -
    -

    --link takes two parameters - first is name of the container we’re linking to and second is the alias for the link name.

    -
    -
    - - - - - -
    -
    Note
    -
    -
    Container Linking
    -
    -

    Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container.

    -
    -
    -

    In our case, target container (WildFly) can see information about source container (MySQL). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. For example, IP address of MySQL server is expoed at $DB_PORT_3306_TCP_ADDR and port of MySQL server is exposed at $DB_PORT_3306_TCP_PORT. These are then used to create the JDBC resource.

    -
    -
    -

    See more about container communication on the Docker website Linking Containers Together

    -
    -
    -
    -
  4. -
  5. -

    See the output as:

    -
    -
    -
    > curl http://dockerhost:8080/employees/resources/employees
    -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  6. -
-
-
-
-
-

7. Build and Deploy Java EE 7 Application

-
-
-

Java EE 7 Simple Sample is a trivial Java EE 7 sample application.

-
-
-

7.1. Build Application

-
-
    -
  1. -

    Clone the repo:

    -
    -
    -
    git clone https://github.com/javaee-samples/javaee7-simple-sample.git
    -
    -
    -
  2. -
  3. -

    Build the application:

    -
    -
    -
    mvn clean package
    -
    -
    -
  4. -
-
-
-
-

7.2. Start Application Server

-
-

Start WildFly server as:

-
-
-
-
docker run --name wildfly -d -p 8080:8080 -v /Users/youruser/tmp/deployments:/opt/jboss/wildfly/standalone/deployments/:rw jboss/wildfly
-
-
-
-

Make sure to replace /Users/youruser/tmp/deployments to a directory on your local machine. Also, make sure this directory already exists. For example, on my machine this directory is /Users/arungupta/tmp/deployments.

-
-
-

This command starts a container named “wildfly”.

-
-
-

The -v flag maps a directory from the host into the container. This will be the directory to put the deployments. rw ensures that the Docker container can write to it.

-
-
- - - - - -
-
Warning
-
-Windows users, please make sure to use -v /c/Users/ notation for drive letters. -
-
-
-

Check logs to verify if the server has started.

-
-
-
-
docker logs -f wildfly
-
-
-
-

Access http://dockerhost:8080 in your browser to make sure the instance is up and running.

-
-
-

Now you’re ready to deploy the application for the first time.

-
-
-
-

7.3. Configure JBoss Developer Studio

-
-

Start JBoss Developer Studio, if not already started.

-
-
-
    -
  1. -

    Select ‘Servers’ tab, create a new server adapter

    -
    -
    -jbds1 -
    -
    Figure 9. Server adapter
    -
    -
  2. -
  3. -

    Assign an existing or create a new WildFly 9.0.0 runtime (changed properties are highlighted.)

    -
    -
    -jbds2 -
    -
    Figure 10. WildFly Runtime Properties
    -
    -
  4. -
  5. -

    If a new runtime needs to be created, pick the directory for WildFly 9.0.0:

    -
    -
    -jbds3 -
    -
    Figure 11. WildFly 9.0.0.Final Runtime
    -
    -
    -

    Click on ‘Finish’.

    -
    -
  6. -
  7. -

    Double-click on the newly selected server to configure server properties:

    -
    -
    -jbds4 -
    -
    Figure 12. Server properties
    -
    -
    -

    The host name is specified to ‘dockerhost’. Two properties on the left are automatically propagated from the previous dialog. Additional two properties on the right side are required to disable to keep deployment scanners in sync with the server.

    -
    -
  8. -
  9. -

    Specify a custom deployment folder on Deployment tab of Server Editor

    -
    -
    -jbds5 -
    -
    Figure 13. Custom deployment folder
    -
    -
  10. -
  11. -

    Right-click on the newly created server adapter and click ‘Start’.

    -
    -
    -jbds6 -
    -
    Figure 14. Started server
    -
    -
  12. -
-
-
-
-

7.4. Deploy Application Using Shared Volumes

-
-
    -
  1. -

    Import javaee7-simple-sample application source code using Import → Existing Maven Projects.

    -
  2. -
  3. -

    Right-click on the project, select ‘Run on Server’ and chose the previously created server.

    -
  4. -
-
-
-

The project runs and displays the start page of the application.

-
-
-
-jbds7 -
-
Figure 15. Start Server
-
-
-

Congratulations!

-
-
-

You’ve deployed your first application to WildFly running in a Docker container from JBoss Developer Studio.

-
-
-

Stop WildFly container when you’re done.

-
-
-
-
docker stop wildfly
-
-
-
-
-

7.5. Deploy Application Using CLI

-
-

The Command Line Interface (CLI) is a tool for connecting to WildFly instances to manage all tasks from command line environment. Some of the tasks that you can do using the CLI are:

-
-
-
    -
  1. -

    Deploy/Undeploy web application in standalone/Domain Mode.

    -
  2. -
  3. -

    View all information about the deployed application on runtime.

    -
  4. -
  5. -

    Start/Stop/Restart Nodes in respective mode i.e. Standalone/Domain.

    -
  6. -
  7. -

    Adding/Deleting resource or subsystems to servers.

    -
  8. -
-
-
-

Lets use the CLI to deploy javaee7-simple-sample to WildFly running in the container.

-
-
-
    -
  1. -

    CLI needs to be locally installed and comes as part of WildFly. This should be available in the previously downloaded WildFly. Unzip into a folder of your choice (e.g. /Users/arungupta/tools/). This will create wildfly-9.0.0.Final directory here. This folder is referred to $WIDLFY_HOME from here on. Make sure to add the /Users/arungupta/tools/wildfly-9.0.0.Final/bin to your $PATH.

    -
  2. -
  3. -

    Run the “wildfly-management” image with fixed port mapping as explained in Fixed Port Mapping.

    -
  4. -
  5. -

    Run the jboss-cli command and connect to the WildFly instance.

    -
    -
    -
    jboss-cli.sh --controller=dockerhost:9990  -u=admin -p=docker#admin -c
    -
    -
    -
    -

    This will show the output as:

    -
    -
    -
    -
    [standalone@dockerhost:9990 /]
    -
    -
    -
  6. -
  7. -

    Deploy the application as:

    -
    -
    -
    deploy <javaee7-simple-sample PATH>target/javaee7-simple-sample-1.10.war --force
    -
    -
    -
  8. -
-
-
-

Now you’ve sucessfully used the CLI to remote deploy the Java EE 7 sample application to WildFly running as docker container.

-
-
-
-

7.6. Deploy Application Using Web Console

-
-

WildFly comes with a web-based administration console. It also relies on the same management APIs that are used by JBoss Developer Tools and the CLI. It provides a simple and easy to use web-based console to manage WildFly instance. For a Docker image, it needs to be explicitly enabled as explained in Enabling WildFly Administration. Once enabled, it can be accessed at http://dockerhost:9990.

-
-
-
-console1 -
-
Figure 16. WildFly Web Console
-
-
-

Username and password credentials are shown in [WildFly_Administration_Credentials].

-
-
- - - - - -
-
Note
-
-
-

You may like to stop and remove the Docker container running WildFly. This can be done as docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f.

-
-
-

Start a new container as docker run -d --name wildfly -p 8080:8080 -p 9990:9990 arungupta/wildfly-management.

-
-
-
-
-

Deploy the application using the console with the following steps:

-
-
-
    -
  1. -

    Go to ‘Deployments’ tab.

    -
    -
    -wildfly9 deployments tab -
    -
    Figure 17. Deployments tab in WildFly Web Console
    -
    -
  2. -
  3. -

    Click on ‘Add’ button.

    -
  4. -
  5. -

    On ‘Add Deployment’ screen, take the default of ‘Upload a new deployment’ and click ‘Next>>’.

    -
  6. -
  7. -

    Click on ‘Choose File’, select <javaee7-simple-sample PATH>/javaee7-simple-sample.war file on your computer. This would be javaee7-simple-sample/target/javaee7-simple-sample.war from Build Application.

    -
  8. -
  9. -

    Click on ‘Next>>’.

    -
  10. -
  11. -

    Select ‘Enable’ checkbox.

    -
    -
    -wildfly9 add deployments -
    -
    Figure 18. Enable a deployment
    -
    -
  12. -
  13. -

    Click ‘Finish’.

    -
    -
    -wildfly9 javaee7 simple sample deployed -
    -
    Figure 19. Java EE 7 Simple Sample Deployed
    -
    -
  14. -
-
-
-

This will complete the deployment of the Java EE 7 application using Web Console. The output can be seen out http://dockerhost:8080/javaee7-simple-sample and looks like:

-
-
-
-wildfly9 javaee7 simple sample output -
-
Figure 20. Java EE 7 Simple Sample Output
-
-
-
-

7.7. Deploy Application Using Management API

-
-

A standalone WildFly process, process can be configured to listen for remote management requests using its “native management interface”. The CLI tool that comes with the application server uses this interface, and user can develop custom clients that use it as well. By default, WildFly management interface listens on 127.0.0.1. When running inside a Docker container, the network interface should be bound to all publicly assigned addresses. This can be easily changed by biding to 0.0.0.0 instead of 127.0.0.1.

-
-
-
    -
  1. -

    Start another WildFly instance again:

    -
    -
    -
    docker run -d --name wildfly -p 8080:8080 -p 9990:9990 arungupta/wildfly-management
    -
    -
    -
    -

    In addition to application port 8080, the administration port 9990 is exposed as well. The WildFly image that is used has tweaked the start script such that the management interface is bound to 0.0.0.0.

    -
    -
  2. -
  3. -

    Create a new server adapter in JBoss Developer Studio and name it “WildFly 9.0.0-Management”. Specify the host name as ‘dockerhost’.

    -
    -
    -jbds8 -
    -
    -
  4. -
  5. -

    Click on ‘Next>’ and change the values as shown.

    -
    -
    -jbds9 -
    -
    Figure 21. Create New Server Adapter
    -
    -
  6. -
  7. -

    Take the default values in ‘Remote System Integration’ and click on ‘Finish’.

    -
  8. -
  9. -

    Change server properties by double clicking on the newly created server adapter. Specify admin credentials (username: docker, password: docker#admin). Note, you need to delete the existing password and use this instead:

    -
    -
    -jbds10 -
    -
    Figure 22. Management Login Credentials
    -
    -
  10. -
  11. -

    Right-click on the newly created server adapter and click ‘Start’. Status quickly changes to ‘Started’ as shown.

    -
    -
    -jbds11 -
    -
    Figure 23. Synchronized WildFly Server
    -
    -
  12. -
  13. -

    Right-click on the javaee7-simple-sample project, select ‘Run on Server’ and choose this server. The project runs and displays the start page of the application.

    -
  14. -
  15. -

    Stop WildFly when you’re done.

    -
    -
    -
    docker stop wildfly
    -
    -
    -
  16. -
-
-
-
-
-
-

8. Docker Maven Plugin

-
-
-

Maven plugin allows you to manage Docker images and containers from pom.xml. It comes with predefined goals:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GoalDescription

docker:start

Create and start containers

docker:stop

Stop and destroy containers

docker:build

Build images

docker:push

Push images to a registry

docker:remove

Remove images from local docker host

docker:logs

Show container logs

-
-

8.1. Run Java EE Application

-
-
    -
  1. -

    Clone the workspace as:

    -
    -
    -
    git clone https://github.com/javaee-samples/javaee7-docker-maven.git
    -
    -
    -
  2. -
  3. -

    Build the image as:

    -
    -
    -
    mvn package -Pdocker
    -
    -
    -
  4. -
  5. -

    Verify the image as:

    -
    -
    -
    docker images
    -REPOSITORY                        TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    -arungupta/javaee7-docker-maven    latest              2e51b3fca40f        4 seconds ago       581.5 MB
    -
    -
    -
  6. -
  7. -

    Run the container as:

    -
    -
    -
    mvn install -Pdocker
    -
    -
    -
  8. -
  9. -

    Access your application at http://dockerhost:8080/javaee7-docker-maven/resources/persons. It shows the output as:

    -
    -
    -
    curl http://dockerhost:8080/javaee7-docker-maven/resources/persons
    -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><person><name>Penny</name></person><person><name>Leonard</name></person><person><name>Sheldon</name></person><person><name>Amy</name></person><person><name>Howard</name></person><person><name>Bernadette</name></person><person><name>Raj</name></person><person><name>Priya</name></person></collection>
    -
    -
    -
  10. -
-
-
-
-

8.2. Understand Plugin Configuration

-
-

pom.xml is updated to include docker-maven-plugin as:

-
-
-
-
<plugin>
-    <groupId>org.jolokia</groupId>
-    <artifactId>docker-maven-plugin</artifactId>
-    <version>0.11.5</version>
-    <configuration>
-        <images>
-            <image>
-                <alias>user</alias>
-                <name>arungupta/javaee7-docker-maven</name>
-                <build>
-                    <from>arungupta/wildfly:8.2</from>
-                    <assembly>
-                        <descriptor>assembly.xml</descriptor>
-                        <basedir>/</basedir>
-                    </assembly>
-                    <ports>
-                        <port>8080</port>
-                    </ports>
-                </build>
-                <run>
-                    <ports>
-                        <port>8080:8080</port>
-                    </ports>
-                </run>
-            </image>
-        </images>
-    </configuration>
-    <executions>
-        <execution>
-            <id>docker:build</id>
-            <phase>package</phase>
-            <goals>
-                <goal>build</goal>
-            </goals>
-        </execution>
-        <execution>
-            <id>docker:start</id>
-            <phase>install</phase>
-            <goals>
-                <goal>start</goal>
-            </goals>
-        </execution>
-    </executions>
-</plugin>
-
-
-
-

Each image configuration has three parts:

-
-
-
    -
  1. -

    Image name and alias

    -
  2. -
  3. -

    <build> that defines how the image is created. Base image, build artifacts and their dependencies, ports to be exposed, etc to be included in the image are specified here. Assembly descriptor format is used to specify the artifacts to be included and is defined in the src/main/docker directory.

    -
    -

    assembly.xml in our case looks like:

    -
    -
    -
    -
    <assembly . . .>
    -  <id>javaee7-docker-maven</id>
    -  <dependencySets>
    -    <dependencySet>
    -      <includes>
    -        <include>org.javaee7.sample:javaee7-docker-maven</include>
    -      </includes>
    -      <outputDirectory>/opt/jboss/wildfly/standalone/deployments/</outputDirectory>
    -      <outputFileNameMapping>javaee7-docker-maven.war</outputFileNameMapping>
    -    </dependencySet>
    -  </dependencySets>
    -</assembly>
    -
    -
    -
  4. -
  5. -

    <run> that defines how the container is run. Ports that need to be exposed are specified here.

    -
  6. -
-
-
-

In addition, package phase is tied to docker:build goal and install phase is tied to docker:start goal.

-
-
-
-
-
-

9. Docker Tools in Eclipse

-
-
-

The Docker tooling is aimed at providing at minimum the same basic level features as the command-line interface, but also provide some advantages by having access to a full fledged UI.

-
-
-

9.1. Install Docker Tools Plugins

-
-

As this is still in early access stage, you will have to install it first:

-
-
-
    -
  1. -

    Use JBoss Developer Studio 9.0 Beta 2.

    -
    -

    Alternatively, download Eclipse Mars latest build and configure JBoss Tools plugin from the update site http://download.jboss.org/jbosstools/updates/nightly/mars/.

    -
    -
  2. -
  3. -

    Open JBoss Developer Studio 9.0 Nightly

    -
  4. -
  5. -

    Add a new site using the menu items: ‘Help’ > ‘Install New Software…​’ > ‘Add…​’.

    -
    -

    Specify the ‘Name:’ as “Docker Nightly” and ‘Location:’ as http://download.eclipse.org/linuxtools/updates-docker-nightly/.

    -
    -
    -
    -jbds docker tools1 -
    -
    Figure 24. Add Docker Tooling To JBoss Developer Studio
    -
    -
  6. -
  7. -

    Expand Linux Tools, select ‘Docker Client’ and ‘Docker Tooling’.

    -
    -
    -jbds docker tools nightly setup -
    -
    Figure 25. Add Docker Tooling
    -
    -
  8. -
  9. -

    Click on ‘Next >’, ‘Next >’, accept the terms of the license agreement, and click on ‘Finish’. This will complete the installation of plugins.

    -
    -

    Restart the IDE for the changes to take effect.

    -
    -
  10. -
-
-
-
-

9.2. Docker Explorer

-
-

The Docker Explorer provides a wizard to establish a new connection to a Docker daemon. This wizard can detect default settings if the user’s machine runs Docker natively (such as in Linux) or in a VM using Boot2Docker (such as in Mac or Windows). Both Unix sockets on Linux machines and the REST API on other OSes are detected and supported. The wizard also allows remote connections using custom settings.

-
-
-
    -
  1. -

    Use the menu ‘Window’, ‘Show View’, ‘Other…​’. Type ‘docker’ to see the output as:

    -
    -
    -jbds docker tools docker view -
    -
    -
  2. -
  3. -

    Select ‘Docker Explorer’ to open Docker Explorer.

    -
    -
    -jbds docker tools docker explorer view -
    -
    -
  4. -
  5. -

    Click on the link in this window to create a connection to Docker Host. Specify the settings as shown:

    -
    -
    -jbds docker tools2 -
    -
    Figure 26. Docker Explorer
    -
    -
    -

    Make sure to get IP address of the Docker Host as:

    -
    -
    -
    -
    docker-machine ip lab
    -
    -
    -
    -

    Also, make sure to specify the correct directory for .docker on your machine.

    -
    -
  6. -
  7. -

    Click on ‘Test Connection’ to check the connection. This should show the output as:

    -
    -
    -jbds docker tools test connection output -
    -
    Figure 27. Docker Explorer
    -
    -
    -

    Click on ‘OK’ and ‘Finish’ to exit out of the wizard.

    -
    -
  8. -
  9. -

    Docker Explorer itself is a tree view that handles multiple connections and provides users with quick overview of the existing images and containers.

    -
    -
    -jbds docker tools3 -
    -
    Figure 28. Docker Explorer Tree View
    -
    -
  10. -
  11. -

    Customize the view by clicking on the arrow in toolbar:

    -
    -
    -jbds docker tools customize view option -
    -
    Figure 29. Docker Explorer Customize View
    -
    -
    -

    Built-in filters can show/hide intermediate and ‘dangling’ images, as well as stopped containers.

    -
    -
    -
    -jbds docker tools customize view wizard -
    -
    Figure 30. Docker Explorer Customize View Wizard
    -
    -
  12. -
-
-
-
-

9.3. Docker Images

-
-

The Docker Images view lists all images in the Docker host selected in the Docker Explorer view. This view allows user to manage images, including:

-
-
-
    -
  1. -

    Pull/push images from/to the Docker Hub Registry (other registries will be supported as well, #469306)

    -
  2. -
  3. -

    Build images from a Dockerfile

    -
  4. -
  5. -

    Create a container from an image

    -
  6. -
-
-
-

Lets take a look at it.

-
-
-
    -
  1. -

    Use the menu ‘Window’, ‘Show View’, ‘Other…​’, select ‘Docker Images’. It shows the list of images on Docker Host:

    -
    -
    -jbds docker tools4 -
    -
    Figure 31. Docker Images View
    -
    -
  2. -
  3. -

    Right-click on the image ending with “wildfly:latest” and click on the green arrow in the toolbar. This will show the following wizard:

    -
    -
    -jbds docker tools run container wizard -
    -
    Figure 32. Docker Run Container Wizard
    -
    -
    -

    By default, all exports ports from the image are mapped to random ports on the host interface. This setting can be changed by unselecting the first checkbox and specify exact port mapping.

    -
    -
    -

    Click on ‘Finish’ to start the container.

    -
    -
  4. -
  5. -

    When the container is started, all logs are streamed into Eclipse Console:

    -
    -
    -jbds docker tools5 -
    -
    Figure 33. Docker Container Logs
    -
    -
  6. -
-
-
-
-

9.4. Docker Containers

-
-

Docker Containers view lets the user manage the containers. The view toolbar provides commands to start, stop, pause, unpause, display the logs and kill containers.

-
-
-
    -
  1. -

    Use the menu ‘Window’, ‘Show View’, ‘Other…​’, select ‘Docker Containers’. It shows the list of running containers on Docker Host:

    -
    -
    -jbds docker tools6 -
    -
    Figure 34. Docker Containers View
    -
    -
  2. -
  3. -

    Pause the container by clicking on the “pause” button in the toolbar (#469310). Show the complete list of containers by clicking on the ‘View Menu’, ‘Show all containers’.

    -
    -
    -jbds docker tools all containers -
    -
    Figure 35. All Docker Containers
    -
    -
  4. -
  5. -

    Select the paused container, and click on the green arrow in the toolbar to restart the container.

    -
  6. -
  7. -

    Right-click on any running container and select “Display Log” to view the log for this container.

    -
    -
    -jbds docker tools display log -
    -
    Figure 36. Eclipse Properties View
    -
    -
  8. -
-
-
-

TODO: Users can also attach an Eclipse console to a running Docker container to follow the logs and use the STDIN to interact with it.

-
-
-
-

9.5. Details on Images and Containers

-
-

Eclipse Properties view is used to provide more information about the containers and images.

-
-
-
    -
  1. -

    Just open the Properties View and click on a Connection, Container, or Image in any of the Docker Explorer View, Docker Containers View, or Docker Images View. This will fill in data in the Properties view.

    -
    -

    Info view is shown as:

    -
    -
    -
    -jbds docker tools properties info -
    -
    Figure 37. Docker Container Properties View Info
    -
    -
    -

    Inspect view is shown as:

    -
    -
    -
    -jbds docker tools properties inspect -
    -
    Figure 38. Docker Container Properties View Inspect
    -
    -
  2. -
-
-
-
-
-
-

10. Test Java EE Applications on Docker

-
-
-

Testing Java EE applications is a very important aspect. Especially when it comes to in-container tests, JBoss Arquillian is well known to make this very easy for Java EE application servers. Picking up where unit tests leave off, Arquillian handles all the plumbing of container management, deployment and framework initialization so you can focus on the task at hand, writing your tests.

-
-
-

With Arquillian, you can use WildFly remote container adapter and connect to any WildFly instance running in a Docker container. But this wouldn’t help with the Docker container lifycycle management.

-
-
-

Arquillian Cube, an extension of Arquillian, allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually. This extension allows to start a Docker container with a server installed, deploy the required deployable file within it and execute Arquillian tests.

-
-
-

The key point here is that if Docker is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before.

-
-
-
    -
  1. -

    Check out the workspace:

    -
    -
    -
    git clone http://github.com/javaee-samples/javaee-arquillian-cube
    -
    -
    -
  2. -
  3. -

    Edit src/test/resources/arquillian.xml file and change the IP address specified in serverUri property value to point to your Docker host’s IP. This can be found out as:

    -
    -
    -
    docker-machine ip lab
    -
    -
    -
  4. -
  5. -

    Run the tests as:

    -
    -
    -
    mvn test
    -
    -
    -
    -

    This will create a container using the image defined in src/test/resources/wildfly/Dockerfile. The container qualifier in arquillian.xml defines the directory name in src/test/resources directory.

    -
    -
    - - - - - -
    -
    Note
    -
    -
    -

    A pre-built image can be used by specifying:

    -
    -
    -
    -
    wildfly:
    -  image: jboss/wildfly
    -
    -
    -
    -

    instead of

    -
    -
    -
    -
    wildfly:
    -  buildImage:
    -    dockerfileLocation: src/test/resources/wildfly
    -
    -
    -
    -
    -
    -

    By default, the “cube” profile is activated and this includes all the required dependencies.

    -
    -
    -

    The result is shown as:

    -
    -
    -
    -
    Running org.javaee7.sample.PersonDatabaseTest
    -Jun 16, 2015 9:23:04 AM org.jboss.arquillian.container.impl.MapObject populate
    -WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.remote.RemoteContainerConfiguration
    -Unused property entries: {target=wildfly:8.1.0.Final:remote}
    -Supported property names: [managementAddress, password, managementPort, managementProtocol, username]
    -Jun 16, 2015 9:23:13 AM org.xnio.Xnio <clinit>
    -INFO: XNIO version 3.2.0.Beta4
    -Jun 16, 2015 9:23:13 AM org.xnio.nio.NioXnio <clinit>
    -INFO: XNIO NIO Implementation Version 3.2.0.Beta4
    -Jun 16, 2015 9:23:13 AM org.jboss.remoting3.EndpointImpl <clinit>
    -INFO: JBoss Remoting version (unknown)
    -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.406 sec - in org.javaee7.sample.PersonDatabaseTest
    -
    -Results :
    -
    -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    -
    -[INFO] ------------------------------------------------------------------------
    -[INFO] BUILD SUCCESS
    -[INFO] ------------------------------------------------------------------------
    -
    -
    -
  6. -
  7. -

    In arquillian.xml, add the following property:

    -
    -
    -
    <property name="connectionMode">STARTORCONNECT</property>
    -
    -
    -
    -

    This bypasses the create/start Cube commands if a Docker Container with the same name is already running on the target system.

    -
    -
    -

    This allows you to prestart the containers manually during development and just connect to them to avoid the extra cost of starting the Docker Containers for each test run. This assumes you are not changing the actual definition of the Docker Container itself.

    -
    -
  8. -
-
-
-
-
-

11. Multiple Containers Using Docker Compose

-
-
-
-Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running. -
-
-— github.com/docker/compose -
-
-
-

An application using Docker containers will typically consist of multiple containers. With Docker Compose, there is no need to write shell scripts to start your containers. All the containers are defined in a configuration file using services, and then docker-compose script is used to start, stop, and restart the application and all the services in that application, and all the containers within that service. The complete list of commands is:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandPurpose

build

Build or rebuild services

help

Get help on a command

kill

Kill containers

logs

View output from containers

port

Print the public port for a port binding

ps

List containers

pull

Pulls service images

restart

Restart services

rm

Remove stopped containers

run

Run a one-off command

scale

Set number of containers for a service

start

Start services

stop

Stop services

up

Create and start containers

-
-

Docker Compose script is only available for OSX and Linux. https://github.com/arun-gupta/docker-java/issues/3 is used for tracking Docker Compose on Windows.

-
-
-

11.1. Configuration File

-
-
    -
  1. -

    Entry point to Compose is docker-compose.yml. Lets use the following file:

    -
    -
    -
    mysqldb:
    -  image: mysql
    -  environment:
    -    MYSQL_DATABASE: sample
    -    MYSQL_USER: mysql
    -    MYSQL_PASSWORD: mysql
    -    MYSQL_ROOT_PASSWORD: supersecret
    -mywildfly:
    -  image: arungupta/wildfly-mysql-javaee7
    -  links:
    -    - mysqldb:db
    -  ports:
    -    - 8080:8080
    -
    -
    - -
    -
      -
    1. -

      Two services defined by the name mysqldb and mywildfly

      -
    2. -
    3. -

      Image name for each service defined using image

      -
    4. -
    5. -

      Environment variables for the MySQL container are defined in environment

      -
    6. -
    7. -

      MySQL container is linked with WildFly container using links

      -
    8. -
    9. -

      Port forwarding is achieved using ports

      -
    10. -
    -
    -
  2. -
-
-
-
-

11.2. Start Services

-
-
    -
  1. -

    All services can be started, in detached mode, by giving the command:

    -
    -
    -
    docker-compose up -d
    -
    -
    -
    -

    And this shows the output as:

    -
    -
    -
    -
    Creating attendees_mysqldb_1...
    -Creating attendees_mywildfly_1...
    -
    -
    -
    -

    An alternate compose file name can be specified using -f.

    -
    -
    -

    An alternate directory where the compose file exists can be specified using -p.

    -
    -
  2. -
  3. -

    Started services can be verified as:

    -
    -
    -
    > docker-compose ps
    -        Name                       Command               State                Ports
    --------------------------------------------------------------------------------------------------
    -attendees_mysqldb_1     /entrypoint.sh mysqld            Up      3306/tcp
    -attendees_mywildfly_1   /opt/jboss/wildfly/customi ...   Up      0.0.0.0:8080->8080/tcp, 9990/tcp
    -
    -
    -
    -

    This provides a consolidated view of all the services started, and containers within them.

    -
    -
    -

    Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual docker ps command:

    -
    -
    -
    -
    > docker ps
    -CONTAINER ID        IMAGE                                    COMMAND                CREATED             STATUS              PORTS                              NAMES
    -3598e545bd2f        arungupta/wildfly-mysql-javaee7:latest   "/opt/jboss/wildfly/   59 seconds ago      Up 58 seconds       0.0.0.0:8080->8080/tcp, 9990/tcp   attendees_mywildfly_1
    -b8cf6a3d518b        mysql:latest                             "/entrypoint.sh mysq   2 minutes ago       Up 2 minutes        3306/tcp                           attendees_mysqldb_1
    -
    -
    -
  4. -
  5. -

    Service logs can be seen as:

    -
    -
    -
    > docker-compose logs
    -Attaching to attendees_mywildfly_1, attendees_mysqldb_1
    -mywildfly_1 | => Starting WildFly server
    -mywildfly_1 | => Waiting for the server to boot
    -mywildfly_1 | =========================================================================
    -mywildfly_1 |
    -mywildfly_1 |   JBoss Bootstrap Environment
    -mywildfly_1 |
    -mywildfly_1 |   JBOSS_HOME: /opt/jboss/wildfly
    -mywildfly_1 |
    -mywildfly_1 |   JAVA: /usr/lib/jvm/java/bin/java
    -mywildfly_1 |
    -mywildfly_1 |   JAVA_OPTS:  -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
    -mywildfly_1 |
    -
    -. . .
    -
    -mywildfly_1 | 15:40:20,866 INFO  [org.jboss.resteasy.spi.ResteasyDeployment] (MSC service thread 1-2) Deploying javax.ws.rs.core.Application: class org.javaee7.samples.employees.MyApplication
    -mywildfly_1 | 15:40:20,914 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017534: Registered web context: /employees
    -mywildfly_1 | 15:40:21,032 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "employees.war" (runtime-name : "employees.war")
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
    -mywildfly_1 | 15:40:21,077 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 9572ms - Started 280 of 334 services (92 services are lazy, passive or on-demand)
    -mysqldb_1   | Running mysql_install_db
    -mysqldb_1   | 2015-06-05 15:38:31 0 [Note] /usr/sbin/mysqld (mysqld 5.6.25) starting as process 27 ...
    -mysqldb_1   | 2015-06-05 15:38:31 27 [Note] InnoDB: Using atomics to ref count buffer pool pages
    -
    -. . .
    -
    -mysqldb_1   | 2015-06-05 15:38:40 1 [Note] Event Scheduler: Loaded 0 events
    -mysqldb_1   | 2015-06-05 15:38:40 1 [Note] mysqld: ready for connections.
    -mysqldb_1   | Version: '5.6.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    -mysqldb_1   | 2015-06-05 15:40:18 1 [Warning] IP address '172.17.0.24' could not be resolved: Name or service not known
    -
    -
    -
  6. -
-
-
-
-

11.3. Verify Application

-
-
    -
  1. -

    Access the application at http://dockerhost:8080/employees/resources/employees/. This is shown in the browser as:

    -
  2. -
-
-
-
-docker compose output -
-
Figure 39. Output From Servers Run Using Docker Compose
-
-
-
-

11.4. Stop Services

-
-
    -
  1. -

    Stop the services as:

    -
    -
    -
    > docker-compose stop
    -Stopping attendees_mywildfly_1...
    -Stopping attendees_mysqldb_1...
    -
    -
    -
  2. -
-
-
- -
-
-
-

12. Java EE Application on Docker Swarm Cluster

-
-
-

Docker Swarm is native clustering for Docker. It allows you create and access to a pool of Docker hosts using the full suite of Docker tools. Because Docker Swarm serves the standard Docker API, any tool that already communicates with a Docker daemon can use Swarm to transparently scale to multiple hosts

-
-
-

12.1. Key Components of Docker Swarm

-
-
-docker swarm components -
-
Figure 40. Key Components of Docker Swarm
-
-
-

Swarm Manager: Docker Swarm has a Manager, that is a pre-defined Docker Host, and is a single point for all administration. The swarm manager orchestrates and schedules containers on the entire cluster. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with #598.

-
-
-

Swarm Nodes: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a Docker Swarm agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node.

-
-
-

Scheduler Strategy: Different scheduler strategies (“binpack”, “spread” (default), and “random”) can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm.

-
-
-

Node Discovery Service: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and ZooKeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and #660 will discuss this.

-
-
-

Standard Docker API: Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means that if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster.

-
-
-

There are lots of other concepts but these are the main ones.

-
-
-
-

12.2. Create a Docker Swarm Cluster

-
-
    -
  1. -

    The easiest way of using Swarm is, by using the official Docker image:

    -
    -
    -
    docker run swarm create
    -
    -
    -
    -

    This command returns a discovery token, referred as <TOKEN> in this document, and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub.

    -
    -
    -

    It shows the output as:

    -
    -
    -
    -
    docker run swarm create
    -Unable to find image 'swarm:latest' locally
    -latest: Pulling from swarm
    -55b38848634f: Pull complete
    -fd7bc7d11a30: Pull complete
    -db039e91413f: Pull complete
    -1e5a49ab6458: Pull complete
    -5d9ce3cdadc7: Pull complete
    -1f26e949f933: Pull complete
    -e08948058bed: Already exists
    -swarm:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
    -Digest: sha256:0e417fe3f7f2c7683599b94852e4308d1f426c82917223fccf4c1c4a4eddb8ef
    -Status: Downloaded newer image for swarm:latest
    -1d528bf0568099a452fef5c029f39b85
    -
    -
    -
    -

    The last line is the <TOKEN>.

    -
    -
    - - - - - -
    -
    Note
    -
    -Make sure to note this cluster id now as there is no means to list it later. This should be fixed with #661. -
    -
    -
  2. -
  3. -

    Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let’s create a Swarm Master next:

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<TOKEN> swarm-master
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in the previous step.

    -
    -
    -

    --swarm configures the machine with Swarm, --swarm-master configures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster.

    -
    -
  4. -
  5. -

    Connect to this newly created master and find some more information about it:

    -
    -
    -
    eval "$(docker-machine env swarm-master)"
    -docker info
    -
    -
    -
    - - - - - -
    -
    Note
    -
    -If you’re on Windows, use the docker-machine env swarm-master command only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/". -
    -
    -
    -

    This will show the output as:

    -
    -
    -
    -
    > docker info
    -Containers: 2
    -Images: 7
    -Storage Driver: aufs
    - Root Dir: /mnt/sda1/var/lib/docker/aufs
    - Backing Filesystem: extfs
    - Dirs: 11
    - Dirperm1 Supported: true
    -Execution Driver: native-0.2
    -Logging Driver: json-file
    -Kernel Version: 4.0.5-boot2docker
    -Operating System: Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015
    -CPUs: 1
    -Total Memory: 996.2 MiB
    -Name: swarm-master
    -ID: DLFR:OQ3E:B5P6:HFFD:VKLI:IOLU:URNG:HML5:UHJF:6JCL:ITFH:DS6J
    -Debug mode (server): true
    -File Descriptors: 22
    -Goroutines: 36
    -System Time: 2015-07-11T00:16:34.29965306Z
    -EventsListeners: 1
    -Init SHA1:
    -Init Path: /usr/local/bin/docker
    -Docker Root Dir: /mnt/sda1/var/lib/docker
    -Username: arungupta
    -Registry: https://index.docker.io/v1/
    -Labels:
    - provider=virtualbox
    -
    -
    -
  6. -
  7. -

    Create a Swarm node

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-01
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in an earlier step.

    -
    -
    -

    Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by --swarm-discovery token://…​ and specifying the cluster id obtained earlier.

    -
    -
  8. -
  9. -

    To make it a real cluster, let’s create a second node:

    -
    -
    -
    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-02
    -
    -
    -
    -

    Replace <TOKEN> with the cluster id obtained in the previous step.

    -
    -
  10. -
  11. -

    List all the nodes created so far:

    -
    -
    -
    docker-machine ls
    -
    -
    -
    -

    This shows the output similar to the one below:

    -
    -
    -
    -
    docker-machine ls
    -NAME            ACTIVE   DRIVER       STATE     URL                         SWARM
    -lab                      virtualbox   Running   tcp://192.168.99.101:2376
    -summit2015               virtualbox   Running   tcp://192.168.99.100:2376
    -swarm-master    *        virtualbox   Running   tcp://192.168.99.102:2376   swarm-master (master)
    -swarm-node-01            virtualbox   Running   tcp://192.168.99.103:2376   swarm-master
    -swarm-node-02            virtualbox   Running   tcp://192.168.99.104:2376   swarm-master
    -
    -
    -
    -

    The machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example, “lab” and “summit2015” are standalone machines where as all other machines are part of the “swarm-master” cluster. The Swarm master is also identified by (master) in the SWARM column.

    -
    -
  12. -
  13. -

    Connect to the Swarm cluster and find some information about it:

    -
    -
    -
    eval "$(docker-machine env --swarm swarm-master)"
    -docker info
    -
    -
    -
    -

    This shows the output as:

    -
    -
    -
    -
    > docker info
    -Containers: 4
    -Images: 3
    -Role: primary
    -Strategy: spread
    -Filters: affinity, health, constraint, port, dependency
    -Nodes: 3
    - swarm-master: 192.168.99.102:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-01: 192.168.99.103:2376
    -  └ Containers: 1
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-02: 192.168.99.104:2376
    -  └ Containers: 1
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    -CPUs: 3
    -Total Memory: 3.065 GiB
    -
    -
    -
    -

    There are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers.

    -
    -
  14. -
  15. -

    List nodes in the cluster with the following command:

    -
    -
    -
    docker run swarm list token://<TOKEN>
    -
    -
    -
    -

    This shows the output as:

    -
    -
    -
    -
    > docker run swarm list token://1d528bf0568099a452fef5c029f39b85
    -192.168.99.103:2376
    -192.168.99.104:2376
    -192.168.99.102:2376
    -
    -
    -
  16. -
-
-
-
-

12.3. Deploy Java EE Application to Docker Swarm Cluster

-
-

The complete cluster is in place now, and we need to deploy the Java EE application to it.

-
-
-

Swarm takes care for the distribution of deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in Deploy Java EE 7 Application (Container Linking).

-
-
-
    -
  1. -

    Start MySQL server as:

    -
    -
    -
    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
    -
    -
    -
    -

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

    -
    -
  2. -
  3. -

    Start WildFly and deploy Java EE 7 application as:

    -
    -
    -
    docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
    -
    -
    -
    -

    This is using the Docker Container Linking explained earlier.

    -
    -
  4. -
  5. -

    Check state of the cluster as:

    -
    -
    -
    > docker info
    -Containers: 7
    -Images: 5
    -Role: primary
    -Strategy: spread
    -Filters: affinity, health, constraint, port, dependency
    -Nodes: 3
    - swarm-master: 192.168.99.102:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-01: 192.168.99.103:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-02: 192.168.99.104:2376
    -  └ Containers: 3
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    -CPUs: 3
    -Total Memory: 3.065 GiB
    -
    -
    -
    -

    “swarm-node-02” is running three containers and so lets look at the list of running containers:

    -
    -
    -
    -
    > eval "$(docker-machine env swarm-node-02)"
    -> docker ps -a
    -CONTAINER ID        IMAGE                             COMMAND                CREATED              STATUS              PORTS                    NAMES
    -805f3587f5df        arungupta/wildfly-mysql-javaee7   "/opt/jboss/wildfly/   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   mywildfly
    -ababc544df97        mysql                             "/entrypoint.sh mysq   5 minutes ago        Up 5 minutes        0.0.0.0:3306->3306/tcp   mysqldb
    -45b015bc79f4        swarm:latest                      "/swarm join --addr    17 minutes ago       Up 17 minutes       2375/tcp                 swarm-agent
    -
    -
    -
  6. -
  7. -

    Access the application as:

    -
    -
    -
    curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees
    -
    -
    -
    -

    to see the output as:

    -
    -
    -
    -
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  8. -
-
-
-
-

12.4. Deploy Java EE Application to Docker Swarm Cluster using Docker Compose

-
-

Multiple Containers Using Docker Compose explains how multi container applications can be easily started using Docker Compose.

-
-
-
    -
  1. -

    Connect to ‘swarm-node-02’:

    -
    -
    -
    eval "$(docker-machine env swarm-node-02)"
    -
    -
    -
  2. -
  3. -

    Stop the MySQL and WildFly containers:

    -
    -
    -
    docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f
    -docker ps -a | grep mysql | awk '{print $1}' | xargs docker rm -f
    -
    -
    -
  4. -
  5. -

    Use the docker-compose.yml file explained in Multiple Containers Using Docker Compose to start the containers as:

    -
    -
    -
    docker-compose up -d
    -Creating wildflymysqljavaee7_mysqldb_1...
    -Creating wildflymysqljavaee7_mywildfly_1...
    -
    -
    -
  6. -
  7. -

    Check the containers running in the cluster as:

    -
    -
    -
    eval "$(docker-machine env --swarm swarm-master)"
    -docker info
    -
    -
    -
    -

    to see the output as:

    -
    -
    -
    -
    docker info
    -Containers: 7
    -Images: 5
    -Role: primary
    -Strategy: spread
    -Filters: affinity, health, constraint, port, dependency
    -Nodes: 3
    - swarm-master: 192.168.99.102:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-01: 192.168.99.103:2376
    -  └ Containers: 2
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    - swarm-node-02: 192.168.99.104:2376
    -  └ Containers: 3
    -  └ Reserved CPUs: 0 / 1
    -  └ Reserved Memory: 0 B / 1.022 GiB
    -  └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
    -CPUs: 3
    -Total Memory: 3.065 GiB
    -
    -
    -
  8. -
  9. -

    Connect to ‘swarm-node-02’ again:

    -
    -
    -
    eval "$(docker-machine env swarm-node-02)"
    -
    -
    -
    -

    and see the list of running containers as:

    -
    -
    -
    -
    docker ps -a
    -CONTAINER ID        IMAGE                             COMMAND                CREATED             STATUS              PORTS                    NAMES
    -b1e7d9bd2c09        arungupta/wildfly-mysql-javaee7   "/opt/jboss/wildfly/   38 seconds ago      Up 37 seconds       0.0.0.0:8080->8080/tcp   wildflymysqljavaee7_mywildfly_1
    -ac9c967e4b1d        mysql:latest                      "/entrypoint.sh mysq   38 seconds ago      Up 38 seconds       3306/tcp                 wildflymysqljavaee7_mysqldb_1
    -45b015bc79f4        swarm:latest                      "/swarm join --addr    20 minutes ago      Up 20 minutes       2375/tcp                 swarm-agent
    -
    -
    -
  10. -
  11. -

    Application can then be accessed again using:

    -
    -
    -
    curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees
    -
    -
    -
    -

    and shows the output as:

    -
    -
    -
    -
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  12. -
-
-
-

Add container visualiation using https://github.com/javaee-samples/docker-java/issues/55.

-
-
-
-
-
-

13. Java EE Application on Kubernetes Cluster

-
-
-
-Kubernetes is an open source system for managing containerized applications across multiple hosts, providing basic mechanisms for deployment, maintenance, and scaling of applications. -
-
-— github.com/GoogleCloudPlatform/kubernetes/ -
-
-
-

Kubernetes, or “k8s” in short, allows the user to provide declarative primitives for the desired state, for example “need 5 WildFly servers and 1 MySQL server running”. Kubernetes self-healing mechanisms, such as auto-restarting, re-scheduling, and replicating containers then ensure this state is met. The user just define the state and Kubernetes ensures that the state is met at all times on the cluster.

-
-
-

How is it related to Docker?

-
-
-

Docker provides the lifecycle management of containers. A Docker image defines a build time representation of the runtime containers. There are commands to start, stop, restart, link, and perform other lifecycle methods on these containers. Kubernetes uses Docker to package, instantiate, and run containerized applications.

-
-
-

How does Kubernetes simplify containerized application deployment?

-
-
-

A typical application would have a cluster of containers across multiple hosts. For example, your web tier (for example Undertow) might run as a few instances, and likely on a set of containers. Similarly, your application tier (for example, WildFly) would run on a different set of containers. The web tier would need to delegate the request to application tier. The web, application, and database tier would generally run on a separate set of containers. These containers would need to talk to each other. Using any of the solutions mentioned above would require scripting to start the containers, and monitoring/bouncing if something goes down. Kubernetes does all of that for the user after the application state has been defined.

-
-
-

13.1. Key Components

-
-

At a very high level, there are three key components:

-
-
-
    -
  1. -

    Pods are the smallest deployable units that can be created, scheduled, and managed. Its a logical collection of containers that belong to an application.

    -
  2. -
  3. -

    Master is the central control point that provides a unified view of the cluster. There is a single master node that control multiple minions.

    -
  4. -
  5. -

    Node is a worker node that run tasks as delegated by the master. Minions can run one or more pods. It provides an application-specific “virtual host” in a containerized environment.

    -
  6. -
-
-
-

A picture is always worth a thousand words and so this is a high-level logical block diagram for Kubernetes:

-
-
-
-kubernetes key components -
-
Figure 41. Kubernetes Key Components
-
-
-

After the 50,000 feet view, lets fly a little lower at 30,000 feet and take a look at how Kubernetes make all of this happen. There are a few key components at Master and Minion that make this happen.

-
-
-
    -
  1. -

    Replication Controller is a resource at Master that ensures that requested number of pods are running on minions at all times.

    -
  2. -
  3. -

    Service is an object on master that provides load balancing across a replicated group of pods. -Label is an arbitrary key/value pair in a distributed watchable storage that the Replication Controller uses for service discovery.

    -
  4. -
  5. -

    Kubelet Each minion runs services to run containers and be managed from the master. In addition to Docker, Kubelet is another key service installed there. It reads container manifests as YAML files that describes a pod. Kubelet ensures that the containers defined in the pods are started and continue running.

    -
  6. -
  7. -

    Master serves RESTful Kubernetes API that validate and configure Pod, Service, and Replication Controller.

    -
  8. -
-
-
-
-

13.2. Start Kubernetes Cluster

-
-

Kubernetes cluster can be easily started using Vagrant. There are two options to start the cluster - first using a downloaded Kubernetes distribution bundle and second by downloading the latest bundle as part of the install.

-
-
-

13.2.1. Using Previously Downloaded Kubernetes Distribution

-
-
    -
  1. -

    Setup a Kubernetes cluster as:

    -
    -
    -
    cd kubernetes
    -
    -export KUBERNETES_PROVIDER=vagrant
    -./cluster/kube-up.sh
    -
    -
    -
    -

    The KUBERNETES_PROVIDER environment variable tells all of the various cluster management scripts which variant to use.

    -
    -
    - - - - - -
    -
    Note
    -
    -This will take a few minutes, so be patience! Vagrant will provision each machine in the cluster with all the necessary components to run Kubernetes. -
    -
    -
    -

    It shows the output as:

    -
    -
    -
    -
    Starting cluster using provider: vagrant
    -... calling verify-prereqs
    -... calling kube-up
    -Using credentials: vagrant:vagrant
    -
    -. . .
    -
    -Cluster validation succeeded
    -Done, listing cluster services:
    -
    -Kubernetes master is running at https://10.245.1.2
    -KubeDNS is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-dns
    -KubeUI is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-ui
    -
    -
    -
    -

    Note down the address for Kubernetes master, https://10.245.1.2 in this case.

    -
    -
  2. -
-
-
-
-

13.2.2. Download and Start the Cluster Together

-
-
    -
  1. -

    Alternatively, the cluster can also be started as:

    -
    -
    -
    > curl -sS https://get.k8s.io | bash
    -Downloading kubernetes release v0.21.1 to /Users/arungupta/tools/kubernetes.tar.gz
    ---2015-07-13 15:56:54--  https://storage.googleapis.com/kubernetes-release/release/v0.21.1/kubernetes.tar.gz
    -Resolving storage.googleapis.com... 74.125.28.128, 2607:f8b0:400e:c02::80
    -Connecting to storage.googleapis.com|74.125.28.128|:443... connected.
    -HTTP request sent, awaiting response... 200 OK
    -Length: 117901998 (112M) [application/x-tar]
    -Saving to: 'kubernetes.tar.gz'
    -
    -kubernetes.tar.gz               100%[=========================================================>] 112.44M  6.21MB/s   in 18s
    -
    -2015-07-13 15:57:13 (6.13 MB/s) - 'kubernetes.tar.gz' saved [117901998/117901998]
    -
    -. . .
    -
    -NAME                 STATUS    MESSAGE              ERROR
    -controller-manager   Healthy   ok                   nil
    -scheduler            Healthy   ok                   nil
    -etcd-0               Healthy   {"health": "true"}   nil
    -Cluster validation succeeded
    -Done, listing cluster services:
    -
    -Kubernetes master is running at https://10.245.1.2
    -KubeDNS is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-dns
    -KubeUI is running at https://10.245.1.2/api/v1/proxy/namespaces/kube-system/services/kube-ui
    -
    -Kubernetes binaries at /Users/arungupta/tools/kubernetes/kubernetes/cluster/
    -You may want to add this directory to your PATH in $HOME/.profile
    -Installation successful!
    -
    -
    -
  2. -
-
-
-
-

13.2.3. Verify the Cluster

-
-
    -
  1. -

    Verify the Kubernetes cluster as:

    -
    -
    -
    kubernetes> vagrant status
    -Current machine states:
    -
    -master                    running (virtualbox)
    -minion-1                  running (virtualbox)
    -
    -This environment represents multiple VMs. The VMs are all listed
    -above with their current state. For more information about a specific
    -VM, run `vagrant status NAME`.
    -
    -
    -
    -

    By default, the Vagrant setup will create a single kubernetes-master and 1 kubernetes-minion. Each VM will take 1 GB, so make sure you have at least 2GB to 4GB of free memory (plus appropriate free disk space).

    -
    -
    - - - - - -
    -
    Note
    -
    -By default, only one minion is created. This can be manipulated by setting an environment variable NUM_MINIONS variable to an integer before invoking kube-up.sh script. -
    -
    -
    -
    -kubernetes cluster vagrant -
    -
    Figure 42. Kubernetes Cluster using Vagrant
    -
    -
    -

    By default, each VM in the cluster is running Fedora, Kubelet is installed into ``systemd'', and all other Kubernetes services are running as containers on Master.

    -
    -
  2. -
  3. -

    Access https://10.245.1.2 (or whatever IP address is assigned to your kubernetes cluster start up log). This may present the warning as shown below:

    -
    -
    -kubernetes master default output certificate -
    -
    -
    -

    Click on ‘Advanced’ and then on ‘Proceed to 10.245.1.2’ to see the output as:

    -
    -
    -
    -kubernetes master default output -
    -
    Figure 43. Kubernetes Output from Master
    -
    -
    -

    Use ‘vagrant’ as the username and ‘vagrant’ as the password.

    -
    -
    -

    Check the list of nodes as:

    -
    -
    -
    -
    > ./cluster/kubectl.sh get nodes
    -NAME         LABELS                              STATUS
    -10.245.1.3   kubernetes.io/hostname=10.245.1.3   Ready
    -
    -
    -
  4. -
  5. -

    Check the list of pods:

    -
    -
    -
    kubernetes> ./cluster/kubectl.sh get po
    -NAME      READY     STATUS    RESTARTS   AGE
    -
    -
    -
  6. -
  7. -

    Check the list of services running:

    -
    -
    -
    kubernetes> ./cluster/kubectl.sh get se
    -NAME         LABELS                                    SELECTOR   IP(S)        PORT(S)
    -kubernetes   component=apiserver,provider=kubernetes   <none>     10.247.0.1   443/TCP
    -
    -
    -
  8. -
  9. -

    Check the list of replication controllers:

    -
    -
    -
    kubernetes> ./cluster/kubectl.sh get rc
    -CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR   REPLICAS
    -
    -
    -
  10. -
-
-
-
-
-

13.3. Deploy Java EE Application (multiple configuration files)

-
-

Pods, and the IP addresses assigned to them, are ephemeral. If a pod dies then Kubernetes will recreate that pod because of its self-healing features, but it might recreate it on a different host. Even if it is on the same host, a different IP address could be assigned to it. And so any application cannot rely upon the IP address of the pod.

-
-
-

Kubernetes services is an abstraction which defines a logical set of pods. A service is typically back-ended by one or more physical pods (associated using labels), and it has a permanent IP address that can be used by other pods/applications. For example, WildFly pod can not directly connect to a MySQL pod but can connect to MySQL service. In essence, Kubernetes service offers clients an IP and port pair which, when accessed, redirects to the appropriate backends.

-
-
-
-kubernetes service -
-
Figure 44. Kubernetes Service
-
-
- - - - - -
-
Note
-
-In this case, all the pods are running on a single minion. This is because, that is the default number for a Kubernetes cluster. The pod can very be on another minion if more number of minions are configured to start in the cluster. -
-
-
-

Any Service that a Pod wants to access must be created before the Pod itself, or else the environment variables will not be populated.

-
-
-

The order of Service and the targeted Pods does not matter. However Service needs to be started before any other Pods consuming the Service are started.

-
-
-

13.3.1. Start MySQL Pod

-
-
    -
  1. -

    Start MySQL Pod:

    -
    -
    -
    ./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-mysql-pod.yaml
    -pods/mysql-pod
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    apiVersion: v1
    -kind: Pod
    -metadata:
    -  name: mysql-pod
    -  labels:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -spec:
    -  containers:
    -    -
    -      name: mysql
    -      image: mysql:latest
    -      env:
    -        -
    -          name: "MYSQL_USER"
    -          value: "mysql"
    -        -
    -          name: "MYSQL_PASSWORD"
    -          value: "mysql"
    -        -
    -          name: "MYSQL_DATABASE"
    -          value: "sample"
    -        -
    -          name: "MYSQL_ROOT_PASSWORD"
    -          value: "supersecret"
    -      ports:
    -        -
    -          containerPort: 3306
    -
    -
    -
  2. -
  3. -

    Get status of the Pod:

    -
    -
    -
    kubernetes> ./cluster/kubectl.sh get -w po
    -NAME        READY     STATUS    RESTARTS   AGE
    -mysql-pod   0/1       Pending   0          4s
    -NAME        READY     STATUS    RESTARTS   AGE
    -mysql-pod   0/1       Running   0          44s
    -mysql-pod   1/1       Running   0         44s
    -
    -
    -
    -

    -w watches for changes to the requested object. Wait for the MySQL pod to be in Running status.

    -
    -
  4. -
-
-
-
-

13.3.2. Start MySQL service

-
-
    -
  1. -

    Start MySQL Service:

    -
    -
    -
    ./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-mysql-service.yaml
    -services/mysql-service
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    apiVersion: v1
    -kind: Service
    -metadata:
    -  name: mysql-service
    -  labels:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -spec:
    -  ports:
    -    # the port that this service should serve on
    -    - port: 3306
    -  # label keys and values that must match in order to receive traffic for this service
    -  selector:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -
    -
    -
    -

    Once again, the label “context: docker-k8s-lab” is used. This simplifies querying the created pods later on.

    -
    -
  2. -
  3. -

    Get status of the Service:

    -
    -
    -
    ./cluster/kubectl.sh get -w se
    -NAME            LABELS                                    SELECTOR                                IP(S)          PORT(S)
    -kubernetes      component=apiserver,provider=kubernetes   <none>                                  10.247.0.1     443/TCP
    -mysql-service   context=docker-k8s-lab,name=mysql-pod     context=docker-k8s-lab,name=mysql-pod   10.247.63.43   3306/TCP
    -
    -
    -
    -

    If multiple services are running, then it can be narrowed by specifying the labels:

    -
    -
    -
    -
    ./cluster/kubectl.sh  get -w po -l context=docker-k8s-lab,name=mysql-pod
    -NAME        READY     STATUS    RESTARTS   AGE
    -mysql-pod   1/1       Running   0          4m
    -
    -
    -
    -

    This is also the selector label used by Service to target Pods.

    -
    -
    -

    When a Service is run on a node, the kubelet adds a set of environment variables for each active Service. It supports both Docker links compatible variables and simpler {SVCNAME}_SERVICE_HOST and {SVCNAME}_SERVICE_PORT variables, where the Service name is upper-cased and dashes are converted to underscores.

    -
    -
    -

    Our service name is “mysql-service” and so MYSQL_SERVICE_SERVICE_HOST and MYSQL_SERVICE_SERVICE_PORT variables are available to other pods.

    -
    -
  4. -
-
-
-

Kubernetes also allows services to be resolved using DNS configuration. Send a Pull Request for adding this functionality to the lab as explained in #62.

-
-
-
-

13.3.3. Start WildFly Replication Controller

-
-
    -
  1. -

    Start WildFly replication controller:

    -
    -
    -
    ./cluster/kubectl.sh create -f ../../attendees/kubernetes/app-wildfly-rc.yaml
    -replicationcontrollers/wildfly-rc
    -
    -
    -
    -

    It uses the following configuration file:

    -
    -
    -
    -
    apiVersion: v1
    -kind: ReplicationController
    -metadata:
    -  name: wildfly-rc
    -  labels:
    -    name: wildfly
    -    context: docker-k8s-lab
    -spec:
    -  replicas: 1
    -  template:
    -    metadata:
    -      labels:
    -        name: wildfly
    -    spec:
    -      containers:
    -      - name: wildfly-rc-pod
    -        image: arungupta/wildfly-mysql-javaee7:k8s
    -        ports:
    -        - containerPort: 8080
    -
    -
    -
  2. -
  3. -

    Check status of the Pod inside Replication Controller:

    -
    -
    -
    ./cluster/kubectl.sh get po
    -NAME               READY     STATUS    RESTARTS   AGE
    -mysql-pod          1/1       Running   0          1h
    -wildfly-rc-w2kk5   1/1       Running   0          6m
    -
    -
    -
  4. -
  5. -

    Get IP address of the Pod:

    -
    -
    -
    ./cluster/kubectl.sh get -o template po wildfly-rc-w2kk5 --template={{.status.podIP}}
    -10.246.1.23
    -
    -
    -
  6. -
-
-
-
-

13.3.4. Access the application (using minion)

-
-
    -
  1. -

    Log in to minion and access the application:

    -
    -
    -
    vagrant ssh minion-1
    -Last login: Thu Jul 16 00:24:36 2015 from 10.0.2.2
    -[vagrant@kubernetes-minion-1 ~]$ curl http://10.246.1.23:8080/employees/resources/employees/
    -<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
    -
    -
    -
  2. -
-
-
-
-

13.3.5. Access the application (using proxy)

- -
-
-
-

13.4. Deploy Java EE Application (one configuration file)

-
-

Kubernetes allow multiple resources to be specified in a single configuration file. This allows to create a “Kubernetes Application” that can consists of multiple resources easily.

-
-
-

Previous section showed how to deploy the Java EE application using multiple configuration files. This application can be delpoyed using a single configuration file as well.

-
-
-
    -
  1. -

    Start the application using the configuration file:

    -
    -
    -
    apiVersion: v1
    -kind: Pod
    -metadata:
    -  name: mysql-pod
    -  labels:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -spec:
    -  containers:
    -    -
    -      name: mysql
    -      image: mysql:latest
    -      env:
    -        -
    -          name: "MYSQL_USER"
    -          value: "mysql"
    -        -
    -          name: "MYSQL_PASSWORD"
    -          value: "mysql"
    -        -
    -          name: "MYSQL_DATABASE"
    -          value: "sample"
    -        -
    -          name: "MYSQL_ROOT_PASSWORD"
    -          value: "supersecret"
    -      ports:
    -        -
    -          containerPort: 3306
    -----
    -apiVersion: v1
    -kind: Service
    -metadata:
    -  name: mysql-service
    -  labels:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -spec:
    -  ports:
    -    # the port that this service should serve on
    -    - port: 3306
    -  # label keys and values that must match in order to receive traffic for this service
    -  selector:
    -    name: mysql-pod
    -    context: docker-k8s-lab
    -----
    -apiVersion: v1
    -kind: ReplicationController
    -metadata:
    -  name: wildfly-rc
    -  labels:
    -    name: wildfly
    -    context: docker-k8s-lab
    -spec:
    -  replicas: 1
    -  template:
    -    metadata:
    -      labels:
    -        name: wildfly
    -    spec:
    -      containers:
    -      - name: wildfly-rc-pod
    -        image: arungupta/wildfly-mysql-javaee7:k8s
    -        ports:
    -        - containerPort: 8080
    -
    -
    -
    -

    Notice that each section, one each for MySQL Pod, MySQL Service, and WildFly Replication Controller, is separated by ----.

    -
    -
  2. -
  3. -

    Start the application:

    -
    -
    -
    ./cluster/kubectl.sh create -f ../../attendees/kubernetes/app.yaml
    -pods/mysql-pod
    -services/mysql-service
    -replicationcontrollers/wildfly-rc
    -
    -
    -
  4. -
  5. -

    Access the application using Access the application (using minion) or Access the application (using proxy).

    -
  6. -
-
-
-
-

13.5. Rescheduling Pods

-
-

Replication Controller ensures that specified number of pod “replicas” are running at any one time. If there are too many, the replication controller kills some pods. If there are too few, it starts more.

-
-
-

WildFly Replication Controller is already running with one Pod. Lets delete this Pod and see how a new Pod is automatically rescheduled.

-
-
-
    -
  1. -

    Find the Pod’s name:

    -
    -
    -
    ./cluster/kubectl.sh get po
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-w2kk5   1/1       Running   0          6m
    -
    -
    -
  2. -
  3. -

    Delete the Pod:

    -
    -
    -
    ./cluster/kubectl.sh delete po wildfly-rc-w2kk5
    -pods/wildfly-rc-w2kk5
    -
    -
    -
    -

    Status of the Pods can be seen in another shell:

    -
    -
    -
    -
    ./cluster/kubectl.sh get -w po
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-w2kk5   1/1       Running   0          2m
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-xz6wu   0/1       Pending   0         2s
    -wildfly-rc-xz6wu   0/1       Pending   0         2s
    -wildfly-rc-xz6wu   0/1       Pending   0         12s
    -wildfly-rc-xz6wu   0/1       Running   0         14s
    -wildfly-rc-xz6wu   1/1       Running   0         22s
    -
    -
    -
    -

    Notice how Pod with name “wildfly-rc-w2kk5” was deleted and a new Pod with the name “wildfly-rc-xz6wu” was created.

    -
    -
  4. -
-
-
-
-

13.6. Scaling Pods

-
-

Replication Controller allows dynamic scaling up and down of Pods.

-
-
-
    -
  1. -

    Scale up the number of Pods:

    -
    -
    -
    ./cluster/kubectl.sh scale --replicas=2 rc wildfly-rc
    -scaled
    -
    -
    -
  2. -
  3. -

    Status of the Pods can be seen in another shell:

    -
    -
    -
    ./cluster/kubectl.sh get -w po
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-bgtkg   1/1       Running   0          3m
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-bymu7   0/1       Pending   0          2s
    -wildfly-rc-bymu7   0/1       Pending   0         2s
    -wildfly-rc-bymu7   0/1       Pending   0         2s
    -wildfly-rc-bymu7   0/1       Running   0         3s
    -wildfly-rc-bymu7   1/1       Running   0         12s
    -
    -
    -
    -

    Notice a new Pod with the name “wildfly-rc-bymu7” is created.

    -
    -
  4. -
  5. -

    Scale down the number of Pods:

    -
    -
    -
    ./cluster/kubectl.sh scale --replicas=1 rc wildfly-rc
    -scaled
    -
    -
    -
  6. -
  7. -

    Status of the Pods using -w is not shown correctly #11338. But status of the Pods can be seen correctly as:

    -
    -
    -
    ./cluster/kubectl.sh get po
    -NAME               READY     STATUS    RESTARTS   AGE
    -wildfly-rc-bgtkg   1/1       Running   0          9m
    -
    -
    -
    -

    Notice only one Pod is running now.

    -
    -
  8. -
-
-
-
-

13.7. Application Logs

-
-
    -
  1. -

    Get list of the Pods:

    -
    -
    -
    ./cluster/kubectl.sh get po
    -NAME               READY     STATUS    RESTARTS   AGE
    -mysql-pod          1/1       Running   0          18h
    -wildfly-rc-w2kk5   1/1       Running   0          16h
    -
    -
    -
  2. -
  3. -

    Get logs for the WildFly Pod:

    -
    -
    -
    ./cluster/kubectl.sh logs wildfly-rc-w2kk5
    -=> Starting WildFly server
    -=> Waiting for the server to boot
    -=========================================================================
    -
    -  JBoss Bootstrap Environment
    -
    -  JBOSS_HOME: /opt/jboss/wildfly
    -
    -  . . .
    -
    -
    -
  4. -
-
-
-

Alternatively, the logs can also be seen by logging into the minion:

-
-
-
    -
  1. -

    Log in to Minion-1 VM:

    -
    -
    -
    > vagrant ssh minion-1
    -Last login: Fri Jun  5 23:01:36 2015 from 10.0.2.2
    -[vagrant@kubernetes-minion-1 ~]$
    -
    -
    -
  2. -
  3. -

    Log in as root:

    -
    -
    -
    [vagrant@kubernetes-minion-1 ~]$ su -
    -Password:
    -[root@kubernetes-minion-1 ~]#
    -
    -
    -
    -

    Default root password for VM images created by Vagrant is ‘vagrant’.

    -
    -
  4. -
  5. -

    See the list of Docker containers running on this VM:

    -
    -
    -
    docker ps
    -
    -
    -
  6. -
  7. -

    View WildFly log as:

    -
    -
    -
    docker logs $(docker ps | grep arungupta/wildfly | awk '{print $1}')
    -
    -
    -
  8. -
  9. -

    View MySQL log as:

    -
    -
    -
    docker logs <CID>
    -
    -
    -
  10. -
-
-
-
-

13.8. Delete Kubernetes Resources

-
-

Individual resources (service, replication controller, or pod) can be deleted by using delete command instead of create command. Alternatively, all services and replication controllers can be deleted using a label as:

-
-
-
-
kubectl delete -l se,po context=docker-k8s-lab
-
-
-
-
-

13.9. Stop Kubernetes Cluster

-
-
-
> ./cluster/kube-down.sh
-Bringing down cluster using provider: vagrant
-==> minion-1: Forcing shutdown of VM...
-==> minion-1: Destroying VM and associated drives...
-==> master: Forcing shutdown of VM...
-==> master: Destroying VM and associated drives...
-Done
-
-
-
-
-

13.10. Debug Kubernetes Master

-
-
    -
  1. -

    Log in to the master as:

    -
    -
    -
    vagrant ssh master
    -Last login: Wed Jul 15 20:36:32 2015 from 10.0.2.2
    -[vagrant@kubernetes-master ~]$
    -
    -
    -
  2. -
  3. -

    Log in as root:

    -
    -
    -
    [vagrant@kubernetes-master ~]$ su -
    -Password:
    -[root@kubernetes-master ~]#
    -
    -
    -
    -

    Default root password for VM images created by Vagrant is ‘vagrant’.

    -
    -
  4. -
  5. -

    Check the containers running on master:

    -
    -
    -
    CONTAINER ID        IMAGE                                                                               COMMAND                CREATED             STATUS              PORTS               NAMES
    -dc59a764953c        gcr.io/google_containers/etcd:2.0.12                                                "/bin/sh -c '/usr/lo   20 hours ago        Up 20 hours                             k8s_etcd-container.fa2ab1d9_etcd-server-kubernetes-master_default_7b64ecafde589b94a342982699601a19_2b69c4d5
    -b722e22d3ddb        gcr.io/google_containers/kube-scheduler:d1107ff3b8fcdcbf5a9d78d9d6dbafb1            "/bin/sh -c '/usr/lo   20 hours ago        Up 20 hours                             k8s_kube-scheduler.7501c229_kube-scheduler-kubernetes-master_default_98b354f725c1589ea5a12119795546ae_b81b9740
    -38a73e342866        gcr.io/google_containers/kube-controller-manager:fafaf8100ccc963e643b55e35386d713   "/bin/sh -c '/usr/lo   20 hours ago        Up 20 hours                             k8s_kube-controller-manager.db050993_kube-controller-manager-kubernetes-master_default_f5c25224fbfb2de87e1e5c35e6b3a293_dcd4cb5d
    -01001de6409e        gcr.io/google_containers/kube-apiserver:cff9e185796caa8b281e7d961aea828b            "/bin/sh -c '/usr/lo   20 hours ago        Up 20 hours                             k8s_kube-apiserver.7e06f4e1_kube-apiserver-kubernetes-master_default_829f8c23fd5fc7951253cac7618447fc_b39c0a5d
    -0f8ccb144ece        gcr.io/google_containers/pause:0.8.0                                                "/pause"               20 hours ago        Up 20 hours                             k8s_POD.e4cc795_kube-scheduler-kubernetes-master_default_98b354f725c1589ea5a12119795546ae_eb1efcac
    -0b8f527456c0        gcr.io/google_containers/pause:0.8.0                                                "/pause"               20 hours ago        Up 20 hours                             k8s_POD.e4cc795_kube-apiserver-kubernetes-master_default_829f8c23fd5fc7951253cac7618447fc_5dd4dee7
    -39d9c41ab1a2        gcr.io/google_containers/pause:0.8.0                                                "/pause"               20 hours ago        Up 20 hours                             k8s_POD.e4cc795_kube-controller-manager-kubernetes-master_default_f5c25224fbfb2de87e1e5c35e6b3a293_522972ae
    -d970ddff7046        gcr.io/google_containers/pause:0.8.0                                                "/pause"               20 hours ago        Up 20 hours                             k8s_POD.e4cc795_etcd-server-kubernetes-master_default_7b64ecafde589b94a342982699601a19_fa75b27f
    -
    -
    -
  6. -
-
-
-
-
-
-

14. Common Docker Commands

-
-
-

Here is the list of commonly used Docker commands:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PurposeCommand

Image

Build an image

docker build --rm=true .

Install an image

docker pull ${IMAGE}

List of installed images

docker images

List of installed images (detailed listing)

docker images --no-trunc

Remove an image

docker rmi ${IMAGE_ID}

Remove all untagged images

docker rmi $(docker images | grep “^” | awk “{print $3}”)

Remove all images

docker rm $(docker ps -aq)

Remove dangling images

docker rmi $(docker images --quiet --filter "dangling=true")

Containers

Run a container

docker run

List of running containers

docker ps

List of all containers

docker ps -a

Stop a container

docker stop ${CID}

Stop all running containers

docker stop docker ps -q

List all exited containers

docker ps -a --filter "exited=1"

Remove a container

docker rm ${CID}

Remove container by a regular expression

docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f

Remove all containers

docker rm $(docker ps -aq)

Find IP address of the container

docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID}

Attach to a container

docker attach ${CID}

Open a shell in to a container

docker exec -it ${CID} bash

Get container id for an image by a regular expression

docker ps | grep wildfly | awk '{print $1}'

-
-
-
-

15. References

-
- -
-
-
- - - \ No newline at end of file diff --git a/scripts/jdays-keynote.adoc b/scripts/jdays-keynote.adoc new file mode 100644 index 0000000..160ded5 --- /dev/null +++ b/scripts/jdays-keynote.adoc @@ -0,0 +1,72 @@ += JDays Keynote Script + +== Docker (local dev) + +. `docker swarm init` +. `docker node ls` +. `docker info` +. +. Use `docker-compose.yml`: ++ +``` +version: "3" +services: + db: + image: arungupta/couchbase:travel + ports: + - 8091:8091 + - 8092:8092 + - 8093:8093 + - 11210:11210 + web: + image: arungupta/wildfly-couchbase-javaee:travel + environment: + - COUCHBASE_URI=db + ports: + - 8080:8080 + - 9990:9990 +``` ++ +. Deploy the app: `docker deploy --compose-file=docker-compose.yml webapp` +. `docker stack ls` +. `docker service ls` +. `docker service logs webapp_web` + +== Kubernetes + +. Register a domain: `kubernetes.arungupta.me` +. Create Route53 records +. Create NS records in GoDaddy +. Create a cluster: ++ +``` +kops create cluster \ +--name=kubernetes.arungupta.me \ +--cloud=aws \ +--zones=us-west-2a,us-west-2b,us-west-2c \ +--master-size=m3.medium \ +--node-count=3 \ +--node-size=m3.xlarge \ +--master-zones=us-west-2a,us-west-2b,us-west-2c \ +--state=s3://kops2 \ +--yes +``` + +== DC/OS + +. Launch https://downloads.dcos.io/dcos/stable/aws.html?_ga=1.207445715.1510362819.1478208859[DC/OS CloudFormation template] +. If not done already, download CLI +. `dcos config set core.dcos_url http://DCOS-ElasticLoadBa-OG73USRXKTX-912507967.us-west-1.elb.amazonaws.com` +. `dcos auth login` +. `dcos config show core.dcos_acs_token` +.. Copy the value in `.dcos-token` +. `dcos package install marathon-lb` +. Update `app-definition.json` with `PublicSlaveDnsAddress` +. Update `pom.xml` with `DnsAddress` +. Deploy app: `mvn install -Pdcos` +. Show services deployed at http:// +. Access application: curl http:///airlines/resources/airline + +== AWS ECS + +Show how to create a cluster and talk about service discovery diff --git a/slides/2016-Devoxx-Migrate-VM-to-Containers.key b/slides/2016-Devoxx-Migrate-VM-to-Containers.key new file mode 100644 index 0000000..8aaed2c Binary files /dev/null and b/slides/2016-Devoxx-Migrate-VM-to-Containers.key differ diff --git a/slides/2016-Devoxx-Migrate-VM-to-Containers.pdf b/slides/2016-Devoxx-Migrate-VM-to-Containers.pdf new file mode 100644 index 0000000..dd082a1 Binary files /dev/null and b/slides/2016-Devoxx-Migrate-VM-to-Containers.pdf differ diff --git a/slides/container-orchestration-aws.key b/slides/container-orchestration-aws.key new file mode 100644 index 0000000..089dee9 Binary files /dev/null and b/slides/container-orchestration-aws.key differ diff --git a/slides/container-orchestration-aws.pdf b/slides/container-orchestration-aws.pdf new file mode 100644 index 0000000..fa2c22e Binary files /dev/null and b/slides/container-orchestration-aws.pdf differ diff --git a/slides/course/chapter1.key b/slides/course/chapter1.key new file mode 100644 index 0000000..7835bac Binary files /dev/null and b/slides/course/chapter1.key differ diff --git a/slides/course/chapter2.key b/slides/course/chapter2.key new file mode 100644 index 0000000..113b592 Binary files /dev/null and b/slides/course/chapter2.key differ diff --git a/slides/course/chapter3.key b/slides/course/chapter3.key new file mode 100644 index 0000000..d318d49 Binary files /dev/null and b/slides/course/chapter3.key differ diff --git a/slides/course/chapter4.key b/slides/course/chapter4.key new file mode 100644 index 0000000..f059702 Binary files /dev/null and b/slides/course/chapter4.key differ diff --git a/slides/course/chapter5.key b/slides/course/chapter5.key new file mode 100644 index 0000000..da63f39 Binary files /dev/null and b/slides/course/chapter5.key differ diff --git a/slides/course/chapter6.key b/slides/course/chapter6.key new file mode 100644 index 0000000..56f1230 Binary files /dev/null and b/slides/course/chapter6.key differ diff --git a/slides/course/pre.key b/slides/course/pre.key new file mode 100644 index 0000000..8f6f556 Binary files /dev/null and b/slides/course/pre.key differ diff --git a/slides/docker-introduction.key b/slides/docker-introduction.key index bbcca34..f222026 100644 Binary files a/slides/docker-introduction.key and b/slides/docker-introduction.key differ diff --git a/slides/docker-introduction.pdf b/slides/docker-introduction.pdf index 3543445..fcbe407 100644 Binary files a/slides/docker-introduction.pdf and b/slides/docker-introduction.pdf differ diff --git a/slides/docker-kubernetes-recipes.key b/slides/docker-kubernetes-recipes.key new file mode 100644 index 0000000..613ef9f Binary files /dev/null and b/slides/docker-kubernetes-recipes.key differ diff --git a/slides/docker-kubernetes-recipes.pdf b/slides/docker-kubernetes-recipes.pdf new file mode 100644 index 0000000..e7d41f3 Binary files /dev/null and b/slides/docker-kubernetes-recipes.pdf differ diff --git a/slides/docker-kubernetes.key b/slides/docker-kubernetes.key new file mode 100644 index 0000000..2391b8b Binary files /dev/null and b/slides/docker-kubernetes.key differ diff --git a/slides/docker-kubernetes.pdf b/slides/docker-kubernetes.pdf new file mode 100644 index 0000000..c9a1fb0 Binary files /dev/null and b/slides/docker-kubernetes.pdf differ diff --git a/slides/ecs-introduction.key b/slides/ecs-introduction.key new file mode 100644 index 0000000..e7f6977 Binary files /dev/null and b/slides/ecs-introduction.key differ diff --git a/slides/jdays-keynote.key b/slides/jdays-keynote.key new file mode 100644 index 0000000..e8ccb6e Binary files /dev/null and b/slides/jdays-keynote.key differ diff --git a/slides/kubernetes-introduction.key b/slides/jdays-keynote.pdf similarity index 53% rename from slides/kubernetes-introduction.key rename to slides/jdays-keynote.pdf index d9483de..b9dff05 100644 Binary files a/slides/kubernetes-introduction.key and b/slides/jdays-keynote.pdf differ diff --git a/slides/kubernetes-introduction.pdf b/slides/kubernetes-introduction.pdf deleted file mode 100644 index 993388e..0000000 Binary files a/slides/kubernetes-introduction.pdf and /dev/null differ diff --git a/slides/mesos-introduction.key b/slides/mesos-introduction.key new file mode 100644 index 0000000..3aaee75 Binary files /dev/null and b/slides/mesos-introduction.key differ diff --git a/slides/mesos-introduction.pdf b/slides/mesos-introduction.pdf new file mode 100644 index 0000000..ee9af97 Binary files /dev/null and b/slides/mesos-introduction.pdf differ diff --git a/slides/service-discovery-oscon2017.key b/slides/service-discovery-oscon2017.key new file mode 100644 index 0000000..7a0937b Binary files /dev/null and b/slides/service-discovery-oscon2017.key differ diff --git a/slides/service-discovery-oscon2017.pdf b/slides/service-discovery-oscon2017.pdf new file mode 100644 index 0000000..61936df Binary files /dev/null and b/slides/service-discovery-oscon2017.pdf differ diff --git a/slides/service-discovery.key b/slides/service-discovery.key new file mode 100644 index 0000000..3b7e19c Binary files /dev/null and b/slides/service-discovery.key differ diff --git a/slides/service-discovery.pdf b/slides/service-discovery.pdf new file mode 100644 index 0000000..de3ae9a Binary files /dev/null and b/slides/service-discovery.pdf differ