{"id":73273,"date":"2018-02-13T10:54:36","date_gmt":"2018-02-13T08:54:36","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=73273"},"modified":"2023-12-11T10:31:22","modified_gmt":"2023-12-11T08:31:22","slug":"docker-java-developers-deploy-docker","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html","title":{"rendered":"Docker for Java Developers: Deploy on Docker"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-tutorial-java-developers.html\">Docker Tutorial for Java Developers<\/a>.<\/p>\n<p>In this course, we provide a series of tutorials so that you can develop your own Docker based applications. We cover a wide range of topics, from Docker over command line, to development, testing, deployment and continuous integration. With our straightforward tutorials, you will be able to get your own projects up and running in minimum time. Check it out <a href=\"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-tutorial-java-developers.html\">here<\/a>!<\/em><\/p>\n<div class=\"toc\">\n<h3>Table Of Contents<\/h3>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#units\">2. Containers as Deployment Units<\/a><\/dt>\n<dt><a href=\"#kubernetes\">3. Orchestration using Kubernetes<\/a><\/dt>\n<dt><a href=\"#mesos\">4. Orchestration using Apache Mesos<\/a><\/dt>\n<dt><a href=\"#swarm\">5. Orchestration using Docker Swarm<\/a><\/dt>\n<dt><a href=\"#cloud\">6. Containers in the Cloud<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#ecs\">6.1. Amazon Elastic Container Service<\/a><\/dt>\n<dt><a href=\"#gke\">6.2. Google Kubernetes Engine<\/a><\/dt>\n<dt><a href=\"#aks\">6.3. Azure Container Service<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#conclusions\">7. Conclusions<\/a><\/dt>\n<dt><a href=\"#next\">8. What\u2019s next<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>Many companies have been using container-based virtualization to deploy applications (including JVM based ones) in production way before <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> appearance on the horizon. However, primarily because of <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>, deployment practices using containers turned into the mainstream these days.<\/p>\n<p>In this section of the tutorial we are going to glance over some of the most popular orchestration and cluster management engines (covering a couple of cloud offerings as well) which natively support deployment and lifecycle of the containerized applications.<\/p>\n<p>The topics we are going to talk about are worth of several books (at least!) so the goal of this part would be to serve as an introduction. If you feel a particular interest in any of those, there is a tremendous amount of the resources available in the public access.<\/p>\n<h2><a name=\"units\"><\/a>2. Containers as Deployment Units<\/h2>\n<p>These days containers (in particular, <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> containers) became standardized units of software deployment. They are prepackaged with everything that the applications may need to run: code (or binary), runtime, system tools and libraries, you name it.<\/p>\n<p>Managing and orchestrating the container-based deployments is quite a hot topic and, as we are going to see in a moment, every solution out there offers it right from the start.<\/p>\n<h2><a name=\"kubernetes\"><\/a>3. Orchestration using Kubernetes<\/h2>\n<p>In a rare case you haven\u2019t heard about it yet, <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> is an open-source system for automating deployment, scaling, and management of containerized applications. This is one of the most exciting, innovative and actively evolving projects in the open-source community. Probably, if you or your company is looking for container orchestration solution, <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> is the de-facto choice nowadays.<\/p>\n<p>There are a lot of things which <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> could do for you, but in this part of the tutorial we are going to see how easy it is to deploy our containerized <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application stack, including <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a>, using only minimal subset of the <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> features.<\/p>\n<p>Setting up a full-fledged <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster on the local machine might sound a bit impractical but luckily <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> could be deployed in development mode via <a href=\"https:\/\/kubernetes.io\/docs\/getting-started-guides\/minikube\/#quickstart\">minikube<\/a>. This awesome tool spawns a single-node <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster inside a virtual machine so you could develop on it day-to-day using your laptop or desktop for example.<\/p>\n<p>With the assumption that you <a href=\"https:\/\/kubernetes.io\/docs\/getting-started-guides\/minikube\/#installation\">installed minikube<\/a> on the operating system of your choice, let us move on to the next step and deploy a couple of <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> containers on it.<\/p>\n<pre class=\"brush:bash\">$ minikube start\n<\/pre>\n<p>When <a href=\"https:\/\/kubernetes.io\/docs\/getting-started-guides\/minikube\/#quickstart\">minikube<\/a> is started, we could immediately initiate <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a> deployment, sticking to the same version <code>8.0.2<\/code> which we have been using along this tutorial.<\/p>\n<pre class=\"brush:bash\">$ kubectl run mysql --image=mysql:8.0.2 --env='MYSQL_ROOT_PASSWORD=p$ssw0rd' --env='MYSQL_DATABASE=my_app_db' --env='MYSQL_ROOT_HOST=%' --port=3306\n<\/pre>\n<p>It will take some time and at the end you should be able to see <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a> container (or better to say, <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> pod) up and running:<\/p>\n<pre class=\"brush:bash\">$ kubectl get pod\nNAME                       READY     STATUS    RESTARTS   AGE\nmysql-5d4dbfcd58-6fmck     1\/1       Running   0          22m\n<\/pre>\n<p>Excellent, now we would need to rebuild the <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> image of our <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application we have <a href=\"https:\/\/www.javacodegeeks.com\/2017\/11\/docker-java-developers-build-docker.html\">developed previously<\/a>, using the <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> settings of the deployed <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster (alternatively, we could have used private registry).<\/p>\n<pre class=\"brush:bash\">$ eval $(minikube docker-env)\n$ docker image build \\\n  --build-arg BUILD_VERSION=0.0.1-SNAPSHOT \\\n  -f Dockerfile.build \\\n  -t jcg\/spring-boot-webapp:latest \\\n  -t jcg\/spring-boot-webapp:0.0.1-SNAPSHOT .\n<\/pre>\n<p>With this step completed, we have our <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> image available for deployment in <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> and we could run it as another pod.<\/p>\n<pre class=\"brush:bash\">$ kubectl run spring-boot-webapp --image=jcg\/spring-boot-webapp:latest --env='DB_HOST=mysql.default.svc.cluster.local' --port=19900 --image-pull-policy=Never\n<\/pre>\n<p>Let us check that we have two pods up and running:<\/p>\n<pre class=\"brush:bash\">$ kubectl get pod\nNAME                                  READY     STATUS    RESTARTS   AGE\nmysql-5d4dbfcd58-6fmck                1\/1       Running   0          33m\nspring-boot-webapp-5ff8456bf5-gf5qv   1\/1       Running   0          31m\n<\/pre>\n<p>Last but not least, we have to expose our <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application deployment as <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> service to make it accessible:<\/p>\n<pre class=\"brush:bash\">$ kubectl expose deployment spring-boot-webapp --type=NodePort\n<\/pre>\n<p>And quickly check it is listed among other services:<\/p>\n<pre class=\"brush:bash\">$ kubectl.exe get service\nNAME               TYPE      CLUSTER-IP          EXTERNAL-IP PORT(S     AGE\nkubernetes         ClusterIP 10.96.0.1           443\/TCP                4d\nspring-boot-webapp NodePort  10.109.108.87       19900:30253\/TCP        40s\n<\/pre>\n<p>And that\u2019s basically it, in a few simple steps we have gotten our <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> containers up and running, all managed by <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a>. Let us make sure that the application is actually passing all the health checks:<\/p>\n<pre class=\"brush:bash\">$ curl $(minikube service spring-boot-webapp --url)\/application\/health\n{\n    \"status\":\"UP\",\n    \"details\": {\n        \"diskSpace\": {\n            \"status\":\"UP\",\n            \"details\": {\n                \"total\":17293533184,\n                \"free\":14476333056,\n                \"threshold\":10485760\n            }\n        },\n        \"db\": {\n            \"status\":\"UP\",\n            \"details\": {\n                \"database\":\"MySQL\",\n                \"hello\":1\n            }\n        }\n    }\n}\n<\/pre>\n<p>And it really does! To finish up our discussion regarding <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a>, it is worth to mention that <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> already includes an early native integration with <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> on <a href=\"https:\/\/docs.docker.com\/docker-for-mac\/#kubernetes\">some of the edge channels<\/a>.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h2><a name=\"mesos\"><\/a>4. Orchestration using Apache Mesos<\/h2>\n<p><a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> is arguably the one of the oldest resource and cluster management frameworks in use. It effectively abstracts resources (CPU, memory, storage) away from physical or virtual hardware, allowing to build and operate fault-tolerant and elastic distributed systems. One of its strengths is exceptional level of extensibility and support of containerized application deployments, however it is also known to be quite complex and difficult to operate.<\/p>\n<p>Architecturally, <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> consists of a <code>master<\/code> that manages <code>agents<\/code> (running on each cluster node), and <code>frameworks<\/code> (that run <code>tasks<\/code> on these agents). The master enables fine-grained sharing of resources (CPU, RAM, \u2026) across frameworks by making them <code>resource offers<\/code>. Bounding ourselves to only the necessary components, let us take a look on how <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> cluster could be defined using <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file\/\">docker-compose<\/a> specification.<\/p>\n<pre class=\"brush:bash\">version: \"3\"\n\nservices:\n  zookeeper:\n    image: zookeeper\n    networks:\n      - mesos-network\n    environment:\n      ZOO_TICK_TIME: 2000\n      ZOO_INIT_LIMIT: 10\n      ZOO_SYNC_LIMIT: 5\n      ZOO_MAX_CLIENT_CNXNS: 128\n      ZOO_PORT: 2181\n      ZOO_MY_ID: 1\n\n  mesos-master:\n    image: mesosphere\/mesos-master:1.3.2\n    networks:\n      - mesos-network\n    ports:\n      - \"5050:5050\"\n    environment:\n      MESOS_ZK: zk:\/\/zookeeper:2181\/mesos\n      MESOS_QUORUM: 1\n      MESOS_CLUSTER: docker-compose\n      MESOS_REGISTRY: replicated_log\n    volumes:\n      - \/var\/run\/docker.sock:\/run\/docker.sock\n    depends_on:\n      - zookeeper\n\n  mesos-slave:\n    image: mesosphere\/mesos-slave:1.3.2\n    privileged: true\n    networks:\n      - mesos-network\n    ports:\n      - \"5051:5051\"\n    links:\n      - zookeeper\n      - mesos-master\n    environment:\n      - MESOS_CONTAINERIZERS=docker\n      - MESOS_ISOLATOR=cgroups\/cpu, cgroups\/mem\n      - MESOS_LOG_DIR=var\/log\n      - MESOS_MASTER=zk:\/\/zookeeper:2181\/mesos\n      - MESOS_PORT=5051\n      - MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins\n      - MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs\n      - MESOS_DOCKER_STOP_TIMEOUT=90secs\n      - MESOS_RESOURCES=cpus:2;mem:2080;disk:5600;ports(*):[19000-19999]\n      - MESOS_WORK_DIR=\/var\/lib\/mesos\n      - MESOS_SYSTEMD_ENABLE_SUPPORT=false\n    volumes:\n      - \/var\/run\/docker.sock:\/run\/docker.sock\n    dns:\n      - mesos-dns\n    depends_on:\n      - mesos-master\n      - mesos-dns\n\n  marathon:\n    image: mesosphere\/marathon:v1.5.6\n    networks:\n      - mesos-network\n    environment:\n      - MARATHON_ZK=zk:\/\/zookeeper:2181\/marathon\n      - MARATHON_MASTER=zk:\/\/zookeeper:2181\/mesos\n    ports:\n      - \"8080:8080\"\n    depends_on:\n      - mesos-master\n\n  mesos-dns:\n    image: mesosphere\/mesos-dns:v0.6.0\n    command: [ \"\/usr\/bin\/mesos-dns\", \"-v=2\", \"-config=\/config.json\" ]\n    ports:\n      - 53:53\/udp\n      - 8123:8123\n    volumes:\n      - .\/config.json:\/config.json\n      - \/tmp\n    links:\n      - zookeeper\n    dns:\n      - 8.8.8.8\n      - 8.8.4.4\n    networks:\n      - mesos-network\n\nnetworks:\n    mesos-network:\n       driver: bridge\n<\/pre>\n<p>As we can see, there are quite a few moving parts in there, besides just <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> (and <a href=\"https:\/\/zookeeper.apache.org\/\">Apache Zookeeper<\/a>). In the heart of it is the <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a> framework, the container orchestration platform. <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a> provides a <a href=\"https:\/\/mesosphere.github.io\/marathon\/docs\/marathon-ui.html\">beautiful web UI<\/a> as well as <a href=\"https:\/\/mesosphere.github.io\/marathon\/api-console\/index.html\">REST(ful) APIs<\/a> to manage the application deployments and uses own <a href=\"https:\/\/www.json.org\/\">JSON<\/a>-based specification format. Following our <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application stack, let us take a look on the example of the <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a> deployment descriptor (which is stored inside the <code>mysql.json<\/code> file):<\/p>\n<pre class=\"brush:bash\">{\n  \"id\": \"\/jcg\/mysql\",\n  \"container\": {\n    \"type\": \"DOCKER\",\n    \"docker\": {\n      \"image\": \"mysql:8.0.2\",\n      \"network\": \"BRIDGE\",\n      \"portMappings\": [\n        {\n          \"containerPort\": 3306,\n          \"servicePort\": 3306,\n          \"hostPort\": 0,\n          \"protocol\": \"tcp\"\n        }\n      ],\n      \"parameters\": [\n        {\n          \"key\": \"hostname\",\n          \"value\": \"mysql\"\n        }\n      ]\n    }\n  },\n  \"env\": {\n    \"MYSQL_ROOT_PASSWORD\": \"p$ssw0rd\",\n    \"MYSQL_DATABASE\": \"my_app_db\",\n    \"MYSQL_ROOT_HOST\": \"%\"\n  },\n  \"instances\": 1,\n  \"cpus\": 0.1,\n  \"mem\": 500,\n  \"healthChecks\": [\n    {\n      \"protocol\": \"COMMAND\",\n      \"command\": { \"value\": \"ss -ltn src :3306 | grep 3306\" },\n      \"gracePeriodSeconds\": 10,\n      \"intervalSeconds\": 10,\n      \"timeoutSeconds\": 5,\n      \"maxConsecutiveFailures\": 2\n    }\n  ]\n}\n<\/pre>\n<p>With that, to bring <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a> container to live we just need to submit this descriptor to <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a> by leveraging its <a href=\"https:\/\/mesosphere.github.io\/marathon\/api-console\/index.html\">REST(ful) APIs<\/a> (assuming our <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> is up and running), for example:<\/p>\n<pre class=\"brush:bash\">$ curl -X POST http:\/\/localhost:8080\/v2\/apps -d @mysql.json -H \"Content-type: application\/json\"\n\n{\n  \"id\":\"\/jcg\/mysql\",\n  \"container\":{\n     \u2026\n  },\n  \u2026\n}\n<\/pre>\n<p>Looks good, let us do the same for <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application, starting off from the <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a> deployment descriptor and persist it in the <code>spring-webapp.json<\/code> file.<\/p>\n<pre class=\"brush:bash\">{\n  \"id\": \"\/jcg\/spring-webapp\",\n  \"container\": {\n    \"type\": \"DOCKER\",\n    \"docker\": {\n      \"image\": \"jcg\/spring-boot-webapp:latest\",\n      \"network\": \"BRIDGE\",\n      \"portMappings\": [\n        { \n          \"containerPort\": 19900, \n          \"servicePort\": 19900, \n          \"hostPort\": 19900 \n        }\n      ],\n      \"parameters\": [\n        { \"key\": \"hostname\", \"value\": \"spring-webapp\" }\n      ]\n    }\n  },\n  \"env\": {\n    \"DB_HOST\": \"172.17.0.2\"\n  },\n  \"instances\": 1,\n  \"cpus\": 0.1,\n  \"mem\": 512,\n  \"healthChecks\": [\n    {\n      \"protocol\": \"COMMAND\",\n      \"command\": { \"value\": \"nc -z localhost 19900\" },\n      \"gracePeriodSeconds\": 25,\n      \"intervalSeconds\": 10,\n      \"timeoutSeconds\": 5,\n      \"maxConsecutiveFailures\": 3\n    }\n  ]\n}\n<\/pre>\n<p>Next step would be to submit it to <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a>:<\/p>\n<pre class=\"brush:bash\">$ curl -X POST http:\/\/localhost:8080\/v2\/apps -d @spring-webapp.json -H \"Content-type: application\/json\"\n\n{\n  \"id\":\"\/jcg\/spring-webapp\",\n  \"container\":{\n     \u2026\n  },\n  \u2026\n}\n<\/pre>\n<p>And we are effectively done! Once the deployment is finished, we should be able to see our application stack in operational state using, for example, <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a>\u2019s <a href=\"https:\/\/mesosphere.github.io\/marathon\/docs\/marathon-ui.html\">web UI<\/a>, accessible at <a href=\"http:\/\/localjost:8080\/ui\/\">http:\/\/localjost:8080\/ui\/<\/a>.<\/p>\n<p><figure id=\"attachment_73452\" aria-describedby=\"caption-attachment-73452\" style=\"width: 860px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/marathon-jcg.png\"><img decoding=\"async\" class=\"wp-image-73452 size-full\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/marathon-jcg.png\" alt=\"\" width=\"860\" height=\"255\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/marathon-jcg.png 860w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/marathon-jcg-300x89.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/marathon-jcg-768x228.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><figcaption id=\"caption-attachment-73452\" class=\"wp-caption-text\">Marathon Applications<\/figcaption><\/figure><\/p>\n<p>The curious reader may wonder how we linked those two <a href=\"http:\/\/mesosphere.github.io\/marathon\/\">Marathon<\/a> applications, <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> and <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a>, together. For this particular case, we have been using <a href=\"https:\/\/mesosphere.github.io\/marathon\/docs\/service-discovery-load-balancing.html\">service discovery and load balancing<\/a> capabilities of <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a> fulfilled by <a href=\"https:\/\/mesosphere.github.io\/mesos-dns\/\">Mesos-DNS<\/a>. To illustrate them in action, this is how we can query the IP address of the <a href=\"https:\/\/dev.mysql.com\/doc\/connector-j\/8.0\/en\/\">MySQL<\/a> instance by its name, <code>mysql-jcg.marathon.mesos<\/code>.<\/p>\n<pre class=\"brush:bash\">$ curl http:\/\/localhost:8123\/v1\/hosts\/mysql-jcg.marathon.mesos\n[\n  {\n   \"host\": \"mysql-jcg.marathon.mesos.\",\n   \"ip\": \"172.17.0.2\"\n  }\n]\n<\/pre>\n<p>As usual, let us confirm that <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application is up and running by sending over a HTTP request to its health endpoint:<\/p>\n<pre class=\"brush:bash\">$ curl http:\/\/localhost:19900\/application\/health\n\n{\n    \"details\": {\n        \"db\": {\n            \"details\": {\n                \"database\": \"MySQL\",\n                \"hello\": 1\n            },\n            \"status\": \"UP\"\n        },\n        \"diskSpace\": {\n            \"details\": {\n                \"free\": 44011802624,\n                \"threshold\": 10485760,\n                \"total\": 49536962560\n            },\n            \"status\": \"UP\"\n        }\n    },\n    \"status\": \"UP\"\n}\n<\/pre>\n<p>[ulp id=&#8217;MD25RnPuC2vrVItl&#8217;]<br \/>\n&nbsp;<\/p>\n<h2><a name=\"swarm\"><\/a>5. Orchestration using Docker Swarm<\/h2>\n<p>It has been awhile since <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> has the cluster management and orchestration features embedded in the engine. This orchestration layer is used to be known as <a href=\"https:\/\/github.com\/docker\/swarm\">Docker Swarm<\/a> but later on evolved into, essentially, just a special mode (<a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a>) to run <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a> in.<\/p>\n<p>If you are betting heavily on <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and prefer not to look for anything else, running <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a> in a <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a> could be a good option as an orchestrator. It is fairly easy to get started with as well.<\/p>\n<pre class=\"brush:bash\">$ docker swarm init\n<\/pre>\n<p>Conceptually, there are quite a few differences which swarm mode introduces, beyond just changes in the <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a> itself. First and foremost, you should start thinking in terms of services, not containers. The assumptions about running everything inside single <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> host won\u2019t be accurate anymore as the swarm would very like consist of many <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> hosts distributed over the network.<\/p>\n<p>When running <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a> in a <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a>, we can deploy a complete application (service) stack using already familiar <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file\/\">docker-compose<\/a> specification. There is only one constraint though, the <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file\/\">docker-compose<\/a> file format should be version <code>3 (or above)<\/code> to be compatible between <a href=\"https:\/\/docs.docker.com\/compose\/overview\/\">Docker Compose<\/a> and <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a>\u2019s <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a>.<\/p>\n<p>To see the <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a> in action, let us rework our <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application stack a bit to comply with <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file\/\">docker-compose<\/a> file format version <code>3.3<\/code>.<\/p>\n<pre class=\"brush:bash\">version: '3.3'\n\nservices:\n  mysql:\n    image: mysql:8.0.2\n    environment:\n      - MYSQL_ROOT_PASSWORD=p$$ssw0rd\n      - MYSQL_DATABASE=my_app_db\n      - MYSQL_ROOT_HOST=%\n    healthcheck:\n      test: [\"CMD-SHELL\", \"ss -ltn src :3306 | grep 3306\"]\n      interval: 10s\n      timeout: 5s\n      retries: 3\n    networks:\n      - my-app-network\n\n  java-app:\n    image: jcg\/spring-boot-webapp:latest\n    environment:\n      - DB_HOST=mysql\n    ports:\n      - 19900:19900\n    depends_on:\n      - mysql\n    healthcheck:\n      test: [\"CMD-SHELL\", \"nc -z localhost 19900\"]\n      interval: 10s\n      timeout: 5s\n      retries: 3\n    networks:\n      - my-app-network\n\nnetworks:\n    my-app-network:\n       driver: overlay\n<\/pre>\n<p>Fairly speaking, we didn&#8217;t have to do many changes. Specifically to support the <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a>, there is a dedicated family of commands which has been introduced into <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/cli\/\">docker<\/a> tooling: <code>docker stack<\/code>. We have not talked about them in <a href=\"https:\/\/www.javacodegeeks.com\/2017\/09\/docker-java-developers-docker-command-line.html\">the second part of this tutorial<\/a>, but now is time to do so.<\/p>\n<p>With the <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/stack_deploy\/\">deploy<\/a> command, and <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file\/\">docker-compose<\/a> specification at hand, we could initiate the application stack deployment into the swarm cluster.<\/p>\n<pre class=\"brush:bash\">$ docker stack deploy --compose-file docker-compose.yml springboot-webapp\n<\/pre>\n<p>To see the status of the deployments and also all deployed services we could use <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/stack_services\/\">services<\/a> command, as in the example below (the output has been shortened a bit):<\/p>\n<pre class=\"brush:bash\">$ docker stack services  springboot-webapp\nNAME                        IMAGE                         REPLICAS PORTS\nspringboot-webapp_java-app  jcg\/spring-boot-webapp:latest 1\/1      *:19900-&gt;19900\/tcp\nspringboot-webapp_mysql     mysql:8.0.2                   1\/1   \n<\/pre>\n<p>Awesome, looks like our <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> application is up and running, let us confirm that by sending over a HTTP request to its health endpoint:<\/p>\n<pre class=\"brush:bash\">$ curl http:\/\/localhost:19900\/application\/health\n\n{\n    \"details\": {\n        \"db\": {\n            \"details\": {\n                \"database\": \"MySQL\",\n                \"hello\": 1\n            },\n            \"status\": \"UP\"\n        },\n        \"diskSpace\": {\n            \"details\": {\n                \"free\": 3606978560,\n                \"threshold\": 10485760,\n                \"total\": 19195224064\n            },\n            \"status\": \"UP\"\n        }\n    },\n    \"status\": \"UP\"\n}\n<\/pre>\n<p>It looks exactly what we expected. To conclude, <a href=\"https:\/\/docs.docker.com\/engine\/\">Docker Engine<\/a> in <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">swarm mode<\/a> in an interesting option to consider however it is worth to mention that it is not as popular as <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> or <a href=\"http:\/\/mesos.apache.org\/\">Apache Mesos<\/a>.<\/p>\n<h2><a name=\"cloud\"><\/a>6. Containers in the Cloud<\/h2>\n<p>Every major player in the cloud space is rushing to the market their own managed offerings which intend to support the deployment and orchestration of the containers so you could just drop one and magic happens. Let us quickly glance through them.<\/p>\n<h3><a name=\"ecs\"><\/a>6.1. Amazon Elastic Container Service<\/h3>\n<p><a href=\"https:\/\/docs.aws.amazon.com\/AmazonECS\/latest\/developerguide\/Welcome.html\">Amazon Elastic Container Service<\/a> (or simply <a href=\"https:\/\/docs.aws.amazon.com\/AmazonECS\/latest\/developerguide\/Welcome.html\">Amazon ECS<\/a>) is a highly scalable, fast, container management service that makes it easy to run, stop, and manage <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> containers in the cluster. As you may expect, <a href=\"https:\/\/docs.aws.amazon.com\/AmazonECS\/latest\/developerguide\/Welcome.html\">Amazon ECS<\/a> integrates nicely with many other cloud offerings from <a href=\"https:\/\/aws.amazon.com\/\">Amazon Web Services<\/a> portfolio, including:<\/p>\n<ul>\n<li>AWS Identity and Access Management<\/li>\n<li>Amazon EC2 Auto Scaling<\/li>\n<li>Elastic Load Balancing<\/li>\n<li>Amazon Elastic Container Registry<\/li>\n<li>AWS CloudFormation<\/li>\n<\/ul>\n<p><a href=\"https:\/\/docs.aws.amazon.com\/AmazonECS\/latest\/developerguide\/Welcome.html\">Amazon ECS<\/a> is a regional service that simplifies running application containers in a highly available manner across multiple availability zones within a region.<\/p>\n<h3><a name=\"gke\"><\/a>6.2. Google Kubernetes Engine<\/h3>\n<p><a href=\"https:\/\/cloud.google.com\/kubernetes-engine\/\">Google Kubernetes Engine<\/a> (formerly known as Google Container Engine) is a managed environment for deploying containerized applications. It brings <a href=\"https:\/\/www.google.com\">Google<\/a>\u2019s unique experience and latest innovations in developer productivity, resource efficiency, automated operations, and open source flexibility to accelerate the time to market.<\/p>\n<p>Google has been running production workloads in containers for a very long time, and have incorporated the best of what they learnt into <a href=\"https:\/\/kubernetes.io\">Kubernetes<\/a>, the industry-leading open source container orchestrator which powers <a href=\"https:\/\/cloud.google.com\/kubernetes-engine\/\">Kubernetes Engine<\/a>. It offers (but is not limited to) the following distinguishing features:<\/p>\n<ul>\n<li>Identity &amp; Access Management<\/li>\n<li>Hybrid Networking<\/li>\n<li>Security and Compliance<\/li>\n<li>Integrated Logging &amp; Monitoring<\/li>\n<li>Auto Scale<\/li>\n<li>Auto Upgrade<\/li>\n<li>Auto Repair<\/li>\n<li>Resource Limits<\/li>\n<li>Stateful Application Support<\/li>\n<li><a href=\"https:\/\/www.docker.com\/\">Docker<\/a> Images Support<\/li>\n<li>Fully Managed<\/li>\n<li>OS Built for Containers<\/li>\n<li>Private Container Registry<\/li>\n<li>Fast Consistent Builds<\/li>\n<li>Open Source Portability<\/li>\n<\/ul>\n<h3><a name=\"aks\"><\/a>6.3. Azure Container Service<\/h3>\n<p><a href=\"https:\/\/azure.microsoft.com\/en-ca\/services\/container-service\/\">Azure Container Service<\/a> (AKS) manages the hosted <a href=\"https:\/\/kubernetes.io\">Kubernetes<\/a> environment, making it quick and easy to deploy and manage containerized applications without container orchestration expertise. It also eliminates the burden of ongoing operations and maintenance by provisioning, upgrading, and scaling resources on demand, without the need to take the applications offline.<\/p>\n<p>As a managed <a href=\"https:\/\/kubernetes.io\">Kubernetes<\/a> service, <a href=\"https:\/\/azure.microsoft.com\/en-ca\/services\/container-service\/\">Azure Container Service<\/a> provides:<\/p>\n<ul>\n<li>Automated <a href=\"https:\/\/kubernetes.io\">Kubernetes<\/a> version upgrades and patching<\/li>\n<li>Easy cluster scaling<\/li>\n<li>Self-healing hosted control plane (masters)<\/li>\n<li>Pay only for running agent pool nodes<\/li>\n<\/ul>\n<h2><a name=\"conclusions\"><\/a>7. Conclusions<\/h2>\n<p>In this section of the tutorial we have looked at a number of leading cluster management and orchestration solutions which offer a comprehensive support of the containerized application deployments. By and large, <a href=\"https:\/\/kubernetes.io\">Kubernetes<\/a> is taking a lead here, however every option has own pros and cons.<\/p>\n<h2><a name=\"next\"><\/a>8. What\u2019s next<\/h2>\n<p>In the next, the final part of the tutorial we are going to talk about very important subject of continuous integration practices and how <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> fits into the picture there.<\/p>\n<p>The complete set of configuration and specification files is <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2018\/02\/Section7.zip\">available for download<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can develop your own Docker based applications. We cover a wide range of topics, from Docker over command line, to development, testing, deployment and continuous integration. With our straightforward &hellip;<\/p>\n","protected":false},"author":141,"featured_media":24013,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[936],"class_list":["post-73273","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-docker"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Docker for Java Developers: Deploy on Docker - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Docker for Java Developers: Deploy on Docker - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-13T08:54:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-11T08:31:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Docker for Java Developers: Deploy on Docker\",\"datePublished\":\"2018-02-13T08:54:36+00:00\",\"dateModified\":\"2023-12-11T08:31:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html\"},\"wordCount\":1958,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"keywords\":[\"Docker\"],\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html\",\"name\":\"Docker for Java Developers: Deploy on Docker - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"datePublished\":\"2018-02-13T08:54:36+00:00\",\"dateModified\":\"2023-12-11T08:31:22+00:00\",\"description\":\"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2018\\\/02\\\/docker-java-developers-deploy-docker.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DevOps\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/devops\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Docker for Java Developers: Deploy on Docker\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Docker for Java Developers: Deploy on Docker - Java Code Geeks","description":"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html","og_locale":"en_US","og_type":"article","og_title":"Docker for Java Developers: Deploy on Docker - Java Code Geeks","og_description":"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can","og_url":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2018-02-13T08:54:36+00:00","article_modified_time":"2023-12-11T08:31:22+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","type":"image\/jpeg"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Docker for Java Developers: Deploy on Docker","datePublished":"2018-02-13T08:54:36+00:00","dateModified":"2023-12-11T08:31:22+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html"},"wordCount":1958,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","keywords":["Docker"],"articleSection":["DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html","url":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html","name":"Docker for Java Developers: Deploy on Docker - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","datePublished":"2018-02-13T08:54:36+00:00","dateModified":"2023-12-11T08:31:22+00:00","description":"This article is part of our Academy Course titled Docker Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2018\/02\/docker-java-developers-deploy-docker.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"DevOps","item":"https:\/\/www.javacodegeeks.com\/category\/devops"},{"@type":"ListItem","position":3,"name":"Docker for Java Developers: Deploy on Docker"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/73273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=73273"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/73273\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/24013"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=73273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=73273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=73273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}