{"id":68257,"date":"2017-08-28T13:00:03","date_gmt":"2017-08-28T10:00:03","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=68257"},"modified":"2023-12-11T10:21:32","modified_gmt":"2023-12-11T08:21:32","slug":"docker-java-developers-introduction","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html","title":{"rendered":"Docker for Java Developers: Introduction"},"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=\"#linux\">2. Linux Containers: The Big Bang<\/a><\/dt>\n<dt><a href=\"#docker\">3. Docker: Containers for Masses<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#architecture\">3.1. Architecture<\/a><\/dt>\n<dt><a href=\"#images\">3.2. Images<\/a><\/dt>\n<dt><a href=\"#containers\">3.3. Containers<\/a><\/dt>\n<dt><a href=\"#registries\">3.4. Registries<\/a><\/dt>\n<dt><a href=\"#rpm\">3.5. Image is the new RPM<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#moby\">4. Moby: The Future of Docker<\/a><\/dt>\n<dt><a href=\"#interop\">5. Towards Interoperability<\/a><\/dt>\n<dt><a href=\"#java\">6. Docker and Java<\/a><\/dt>\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>If you have not heard about <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>, then you have probably spent the last few years on some other planet of the Solar system. <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> stormed into our industry and in no time dramatically changed many well-established software development and operational practices and patterns. These days pretty much every organization is using <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> (or equivalent of it), the brave ones even in production, and its adoption is growing at fantastic pace.<\/p>\n<p>In this tutorial we are going to talk about how <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> can help us, <a href=\"https:\/\/www.java.com\/en\/\">Java<\/a> developers, in accomplishing our day to day tasks. The tutorial consists of several parts where we going to touch upon different aspects of <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and its applicability to <a href=\"https:\/\/www.java.com\/en\/\">Java<\/a> applications development.<\/p>\n<p>We will start off by learning the basics:<\/p>\n<ul>\n<li>Why we should invest our time in learning <a href=\"https:\/\/www.docker.com\/\">Docker<\/a><\/li>\n<li>Get to know <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> command line tooling<\/li>\n<li>Using REST fa\u00e7ade to talk to <a href=\"https:\/\/www.docker.com\/\">Docker<\/a><\/li>\n<\/ul>\n<p>Then we will move on to the topics related specifically to <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> in context of <a href=\"https:\/\/www.java.com\/en\/\">Java<\/a> applications right after:<\/p>\n<ul>\n<li>Building<\/li>\n<li>Developing<\/li>\n<li>Testing<\/li>\n<li>Deploying<\/li>\n<li>Continuous Integration \/ Delivery<\/li>\n<\/ul>\n<p>The material we will be going through assumes that you have some basic familiarity with <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and have at least version <strong>17.06.1-ce<\/strong> already <a href=\"https:\/\/docs.docker.com\/engine\/installation\/\">installed<\/a> on the machine (it does not really matter if you are on Linux, Windows or Mac per se).<\/p>\n<h2><a name=\"linux\"><\/a>2. Linux Containers: The Big Bang<\/h2>\n<p>The story, which made <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and friends possible, begins back in 2006, when a couple of awesome engineers at <a href=\"https:\/\/en.wikipedia.org\/wiki\/Google\">Google<\/a> started the work on the feature under the name &#8220;process containers&#8221;.\u00a0 It was later rebranded to &#8220;control groups&#8221; (or <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cgroups\">cgroups<\/a> as we know them today) and was merged into the Linux kernel starting from version <strong>2.6.24<\/strong>, released in January 2008.<\/p>\n<p>Essentially, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cgroups\">cgroups<\/a> is a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_kernel\">Linux kernel<\/a> feature that limits, accounts for, prioritizes and isolates the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Resource_%28computer_science%29\">resource usage<\/a> (CPU, memory, disk I\/O, network, etc.) of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Process_%28computing%29\">processes<\/a>. Most importantly, to support all that the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_kernel\">Linux kernel<\/a> does not need to start any <a href=\"https:\/\/en.wikipedia.org\/wiki\/Virtual_machine\">virtual machines<\/a> or <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypervisor\">hypervisors<\/a>. Along with <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_namespaces\">namespaces<\/a>, another very powerful feature of the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_kernel\">Linux kernel<\/a>, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cgroups\">cgroups<\/a> serve as a fundamental building block for <a href=\"https:\/\/en.wikipedia.org\/wiki\/Operating-system-level_virtualization\">containers<\/a>: operating system-level virtualization.<\/p>\n<p>Container-based virtualization is exceptionally lightweight (comparing to traditional <a href=\"https:\/\/en.wikipedia.org\/wiki\/Virtual_machine\">virtual machines<\/a>), imposes little to no overhead, share the same operating system kernel and do not require special hardware support to perform efficiently. To say it in other words, containers become a new model to wrap the applications so they could be run in isolation on a shared operating system. Although not without the limitations, going with containers becomes a mainstream in the virtualization space nowadays.<\/p>\n<p>To be fair, not all Linux\/Unix distributions use the same mechanisms for operating system-level virtualization. To mention a couple of examples, <a href=\"https:\/\/www.freebsd.org\/\">FreeBSD<\/a> has <a href=\"https:\/\/en.wikipedia.org\/wiki\/FreeBSD_jail\">jails<\/a> for such purposes while <a href=\"https:\/\/en.wikipedia.org\/wiki\/Solaris_(operating_system)\">Solaris<\/a> has the concept of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Solaris_Containers\">zones<\/a>.<\/p>\n<p>So, how to get started with containers? Well, you may have heard abbreviations like <a href=\"https:\/\/linuxcontainers.org\/lxc\/introduction\/\">LXC<\/a> or <a href=\"https:\/\/linuxcontainers.org\/lxd\/introduction\/\">LXD<\/a> which are essentially the entry points for containers management on most of the Linux\/Unix distributions. The thing is, those are somewhat low-level and not easy to start with. But luckily we have <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> and <a href=\"https:\/\/coreos.com\/rkt\">rkt<\/a>, the application-centric container management engines, which right from the inception became the de facto choices for the application developers across the globe.<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=\"docker\"><\/a>3. Docker: Containers for Masses<\/h2>\n<p>So what is <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> essentially? It started off as a powerful and easy to use container engine but these days it would be fair to call it a full-fledged container management platform. It is written in <a href=\"https:\/\/golang.org\/\">Go<\/a> and takes advantage of the Linux kernel features (mostly <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_namespaces\">namespaces<\/a> and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cgroups\">cgroups<\/a>) to do the job. The community edition is downloadable free of charge whereas the enterprise edition is also available through subscription offerings. To settle the stage, along this tutorial we are going to use the features of the community edition only.<\/p>\n<h3><a name=\"architecture\"><\/a>3.1. Architecture<\/h3>\n<p>From the architectural perspective, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> consists of three main parts. In the heart of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> sits the daemon process, <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/dockerd\/\">dockerd<\/a>. In turn, <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/dockerd\/\">dockerd<\/a> relies on another daemon, <a href=\"https:\/\/containerd.io\/\">containerd<\/a>, as the abstraction layer to interface with the Linux kernel <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_namespaces\">namespaces<\/a> and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cgroups\">cgroups<\/a>. The last piece of the puzzle is a set of command line tools (like for example <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/docker\/\">docker<\/a> and <a href=\"https:\/\/docs.docker.com\/compose\/reference\/overview\/\">docker-compose<\/a>), known as Docker CLI, which are able to talk to <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/dockerd\/\">dockerd<\/a> daemon though the <a href=\"https:\/\/docs.docker.com\/engine\/api\/\">Docker Engine API<\/a> it exposes.<\/p>\n<p>Each of the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> components mentioned above deserves own tutorial, so many interesting features and capabilities they provide, though our focus would be primarily centered on <a href=\"https:\/\/docs.docker.com\/engine\/api\/\">Docker Engine API<\/a> and the Docker CLI family (<a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/docker\/\">docker<\/a> and <a href=\"https:\/\/docs.docker.com\/compose\/reference\/overview\/\">docker-compose<\/a>).<\/p>\n<p>One of the strongest arguments in favor of choosing <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> is that it runs natively on the majority of the Linux distributions but it does not stop there. <a href=\"https:\/\/www.docker.com\/docker-mac\">macOS<\/a> and <a href=\"https:\/\/www.docker.com\/docker-windows\">Windows<\/a> operating systems are also supported pretty well, with a <a href=\"https:\/\/docs.docker.com\/toolbox\/overview\/\">few caveats<\/a> to be aware of.<\/p>\n<p>In order to understand how <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> works, we have to unveil a bit its internal model. At any time, if you feel like there are not enough details uncovered about the subject, please do not hesitate to consult the <a href=\"https:\/\/docs.docker.com\/\">official documentation<\/a>.<\/p>\n<h3><a name=\"images\"><\/a>3.2. Images<\/h3>\n<p>In <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a>, everything you do is managing the specific objects. Images and containers are arguably the most important ones however there are others like volumes, networks and plugins, to name a few. All of them we are going to see in action in different sections of the tutorial, starting with images and containers right away.<\/p>\n<p>Image could be treated as a set of instructions on how to create the container. In <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a>, one image could be inherited (or based on) from another image, adding additional instructions on top of base ones. Each image consists of multiple layers, which are effectively immutable. Under the hood these layers are backed by dedicated file systems (by default <a href=\"https:\/\/en.wikipedia.org\/wiki\/UnionFS\">UnionFS<\/a>, but others could be plugged in as well), making them very lightweight and fast.<\/p>\n<p>So \u2026 how could you create such images for your own needs? It is actually pretty simple, to build your own image in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> you create a <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a> which is just a text document that defines the set of steps (or instructions) required to assemble the image (and run it later). Along the way you may decide to <a href=\"https:\/\/docs.docker.com\/engine\/userguide\/eng-image\/baseimages\/\">create\u00a0 completely customized images<\/a> yourself or, in most cases, reference the images created by others, which are published in a <a href=\"#_Registries\">registry<\/a>. To give you a sneak peek on how the <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a>s may look like, here is a quick example:<\/p>\n<pre class=\"brush:bash\">FROM alpine:3.6\nCMD [\"uname\", \"-a\"]\n<\/pre>\n<p>Each instruction in a <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a> creates a new layer so at the end each image has a list of immutable layers, stacked on top of each other, that represent the filesystem differences.<\/p>\n<p>In the upcoming sections we will be writing quite a lot of different <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a>s, closely following the <a href=\"https:\/\/docs.docker.com\/engine\/userguide\/eng-image\/dockerfile_best-practices\/\">best practices and recommendations<\/a>.<\/p>\n<h3><a name=\"containers\"><\/a>3.3. Containers<\/h3>\n<p>When you have your images ready, it is time to bring them to live. Here is where the containers appear on the stage: they are runnable instances of the images. You can run as many of them as your want, assuming the target host (where <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> is installed) has enough resources. All of that is feasible because the containers are well isolated from each other, at least by default (however you have quite a lot of options to control that).<\/p>\n<p>When <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> creates an instance of the <strong>container<\/strong><strong>, <\/strong>it also <strong>adds a new writable layer<\/strong> on top of the underlying stack of image layers, often called the <strong>container layer<\/strong>. All the changes which are made to the running container (such as creating, deleting or modifying files for example) are written to this thin layer.<\/p>\n<p>It is important to think about containers as ephemeral: when a container is terminated (stopped and removed), any changes to its state disappear (unless they are stored in persistent storage).<\/p>\n<p>As of now, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> internally uses its own image format and heavily relies on <a href=\"https:\/\/github.com\/opencontainers\/runc\/tree\/master\/libcontainer\">libcontainer<\/a> and <a href=\"https:\/\/github.com\/opencontainers\/runc\">runc<\/a> for spawning and running the containers.<\/p>\n<h3><a name=\"registries\"><\/a>3.4. Registries<\/h3>\n<p>The purpose of the registries in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> architecture is to store images so they could be shared and used as the base ones. <a href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a> and <a href=\"https:\/\/cloud.docker.com\/\">Docker Cloud<\/a> are the well-known public registries that anyone can use. To keep things simple, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> is configured to look for images on <a href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a> by default.<\/p>\n<p>You may also consider the option to host your own private <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> registry (or registries). There are a lot of good reasons to do that, particularly in the world of enterprises. One of the most crucial ones is security as the public images do not undergo through comprehensive security audit and may have known <a href=\"http:\/\/dl.acm.org\/citation.cfm?id=3029832\">security vulnerabilities or exposures<\/a>. However, the things are getting better as more and more companies maintain so called <a href=\"https:\/\/docs.docker.com\/docker-hub\/official_repos\/\">official repositories<\/a>, which are curated and adhere to higher standards.<\/p>\n<p>To make things even more intriguing, the new player has joined the game of registries recently. The flagship <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> product, <a href=\"https:\/\/docs.docker.com\/docker-store\/\">Docker Store<\/a>, has been announced to become generally available.<br \/>\n[ulp id=&#8217;MD25RnPuC2vrVItl&#8217;]<br \/>\n&nbsp;<\/p>\n<h3><a name=\"rpm\"><\/a>3.5. Image is the new RPM<\/h3>\n<p>With the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> and other container engines becoming more and more popular and widespread, the way we used to package and distribute the application is also changing dramatically. Literally, the image becomes a \u201cnew RPM\u201d in a sense that you could distribute it to any platform where the container engine of your choice is supported (more on that later) and just run it as a container. It is indeed easy, simple and powerful.<\/p>\n<h2><a name=\"moby\"><\/a>4. Moby: The Future of Docker<\/h2>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> has been seeing a lot of changes recently. Driven by initiatives to break <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> into modular components and consolidate all of its open source collaborations, the <a href=\"https:\/\/mobyproject.org\/\">Moby Project<\/a> was born.<\/p>\n<blockquote>\n<p><em>The Moby Project is a new open-source project to advance the software containerization movement and help the ecosystem take containers mainstream. It provides a library of components, a framework for assembling them into custom container-based systems and a place for all container enthusiasts to experiment and exchange ideas. &#8211; <\/em><a href=\"https:\/\/blog.docker.com\/2017\/04\/introducing-the-moby-project\/\"><em>https:\/\/blog.docker.com\/2017\/04\/introducing-the-moby-project\/<\/em><\/a><\/p>\n<\/blockquote>\n<p>As <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> continues to be split up into more components, the <a href=\"https:\/\/mobyproject.org\/\">Moby Project<\/a> will become the home for those components as well, so let us keep an eye on it and look forward to exciting announcements.<\/p>\n<h2><a name=\"interop\"><\/a>5. Towards Interoperability<\/h2>\n<p>With multiple application-centric container engines available at the moment, namely <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> and <a href=\"https:\/\/coreos.com\/rkt\">rkt<\/a> (and very likely more to appear in the future), the obvious question to ask would be: how to pick one? And what happens if you would have to switch to another one along the way?<\/p>\n<p>Indeed, at the moment if you select one container engine over the other, you would probably have to stick to it as the move to alternative may be proven difficult. But there is a hope, thanks to <a href=\"https:\/\/www.opencontainers.org\/\">Open Container Initiative<\/a> (or just <a href=\"https:\/\/www.opencontainers.org\/\">OCI<\/a>), that container engines interoperability would improve significantly, with enough players supporting the common specifications.<\/p>\n<p>We have <a href=\"#_Containers\">mentioned earlier<\/a> that at the moment <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> uses own image format. To our luck, the important milestone towards openness in this space has been achieved recently with the first release of <a href=\"https:\/\/blog.docker.com\/2017\/07\/oci-release-of-v1-0-runtime-and-image-format-specifications\/\">OCI Runtime and Image specifications<\/a>.<\/p>\n<h2><a name=\"java\"><\/a>6. Docker and Java<\/h2>\n<p>There have been a lot of discussions lately regarding any legal consequences or licensing considerations while using <a href=\"https:\/\/www.java.com\/en\/\">Java<\/a> inside the containers. The official <a href=\"https:\/\/www.oracle.com\/index.html\">Oracle<\/a> position on the matter is nicely summarized in the Q&amp;A section:<\/p>\n<blockquote>\n<p><strong><em>Are there any licensing considerations for Oracle Java SE that are unique to Docker?<\/em><\/strong><\/p>\n<p><em>\u00a0No.\u00a0 Docker is a containerization platform and there are no unique or special restrictions in the license for use or redistribution as compared to any operating system, virtualization or packaging format. The Oracle JDK is widely used and adopted in the Docker ecosystem. &#8211; <\/em><a href=\"https:\/\/blogs.oracle.com\/developers\/official-docker-image-for-oracle-java-and-the-openjdk-roadmap-for-containers\"><em>https:\/\/blogs.oracle.com\/developers\/official-docker-image-for-oracle-java-and-the-openjdk-roadmap-for-containers<\/em><\/a><\/p>\n<\/blockquote>\n<p>Although the answer is referring to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> only, it is equally applicable to other container-based virtualization engines as well.<\/p>\n<p>To prove the point, <a href=\"https:\/\/www.oracle.com\/index.html\">Oracle<\/a> has published the official <a href=\"https:\/\/store.docker.com\/images\/oracle-serverjre-8\">Oracle Java 8 SE (Server JRE)<\/a> image into the <a href=\"https:\/\/store.docker.com\/\">Docker Store<\/a>, one of the places to find the trusted commercial and free software distributed as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> Images.<\/p>\n<h2><a name=\"conclusions\"><\/a>7. Conclusions<\/h2>\n<p>In this introductory section of the tutorial we have looked a bit into evolution of virtualization mechanisms in the Linux\/Unix operating systems. We have learned at the high level what are images, containers, their benefits comparing to traditional <a href=\"https:\/\/en.wikipedia.org\/wiki\/Virtual_machine\">virtual machines<\/a> and how we could get started using them.<\/p>\n<h2><a name=\"next\"><\/a>8. What\u2019s next<\/h2>\n<p>We have not done much along this section while just going through bare listing of facts and terms. However, roll up your sleeves, in the next section we are going to take a closer look on <a href=\"https:\/\/en.wikipedia.org\/wiki\/Docker_%28software%29\">Docker<\/a> container engine by learning its tooling and commands.<\/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":[],"class_list":["post-68257","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"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: Introduction - 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\/2017\/08\/docker-java-developers-introduction.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: Introduction - 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\/2017\/08\/docker-java-developers-introduction.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=\"2017-08-28T10:00:03+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-11T08:21:32+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=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Docker for Java Developers: Introduction\",\"datePublished\":\"2017-08-28T10:00:03+00:00\",\"dateModified\":\"2023-12-11T08:21:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html\"},\"wordCount\":2189,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html\",\"name\":\"Docker for Java Developers: Introduction - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2014\\\/04\\\/docker-logo.jpg\",\"datePublished\":\"2017-08-28T10:00:03+00:00\",\"dateModified\":\"2023-12-11T08:21:32+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\\\/2017\\\/08\\\/docker-java-developers-introduction.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/08\\\/docker-java-developers-introduction.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\\\/2017\\\/08\\\/docker-java-developers-introduction.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: Introduction\"}]},{\"@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: Introduction - 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\/2017\/08\/docker-java-developers-introduction.html","og_locale":"en_US","og_type":"article","og_title":"Docker for Java Developers: Introduction - 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\/2017\/08\/docker-java-developers-introduction.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-08-28T10:00:03+00:00","article_modified_time":"2023-12-11T08:21:32+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":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Docker for Java Developers: Introduction","datePublished":"2017-08-28T10:00:03+00:00","dateModified":"2023-12-11T08:21:32+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html"},"wordCount":2189,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","articleSection":["DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html","url":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html","name":"Docker for Java Developers: Introduction - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/04\/docker-logo.jpg","datePublished":"2017-08-28T10:00:03+00:00","dateModified":"2023-12-11T08:21:32+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\/2017\/08\/docker-java-developers-introduction.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/08\/docker-java-developers-introduction.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\/2017\/08\/docker-java-developers-introduction.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: Introduction"}]},{"@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\/68257","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=68257"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/68257\/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=68257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=68257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=68257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}