{"id":198,"date":"2014-11-19T16:24:05","date_gmt":"2014-11-19T05:24:05","guid":{"rendered":"https:\/\/icicimov.com\/blog\/?p=198"},"modified":"2017-01-02T16:32:44","modified_gmt":"2017-01-02T05:32:44","slug":"building-custom-docker-images-and-configuring-with-ansible","status":"publish","type":"post","link":"https:\/\/icicimov.com\/blog\/?p=198","title":{"rendered":"Building custom Docker images and configuring with Ansible"},"content":{"rendered":"<p>Due to ever rising popularity of Docker this page will provide a walk through process of building custom Encompass Docker images and creating containers. The image configuration will be executed with our existing Ansible repository. We will store this images in our private Docker image repository (each account gets one free private repository) or in our own image storage created on a EC2 server or S3 bucket.<\/p>\n<p>Visit <a href=\"https:\/\/docker.encompasshost.com\/\">Docker Encompass<\/a> to check the most recent DevTest version of the Encompass application fully hosted in Docker containers.<\/p>\n<h2>Docker<\/h2>\n<p>Docker can be easily install via packages provided in all major Linux distributions. For Ubuntu-14.04 we run:<\/p>\n<pre><code>$ sudo sh -c \"wget -qO- https:\/\/get.docker.io\/gpg | apt-key add -\"\n$ sudo sh -c \"echo deb http:\/\/get.docker.io\/ubuntu docker main &gt; \/etc\/apt\/sources.list.d\/docker.list\"\n$ sudo aptitude update\n$ sudo aptitude install lxc-docker apparmor\n<\/code><\/pre>\n<p>To confirm successful installation:<\/p>\n<pre><code>$ sudo docker info\nContainers: 0\nImages: 0\nStorage Driver: aufs\n Root Dir: \/var\/lib\/docker\/aufs\n Dirs: 0\nExecution Driver: native-0.2\nKernel Version: 3.13.0-39-generic\nOperating System: Ubuntu precise (12.04.5 LTS)\nWARNING: No swap limit support\n\n$ sudo docker version\nClient version: 1.3.1\nClient API version: 1.15\nGo version (client): go1.3.3\nGit commit (client): 4e9bbfa\nOS\/Arch (client): linux\/amd64\nServer version: 1.3.1\nServer API version: 1.15\nGo version (server): go1.3.3\nGit commit (server): 4e9bbfa\n<\/code><\/pre>\n<p>Download and run the check-config script from the docker repository https:\/\/github.com\/docker\/docker.git to check if all dependencies are satisfied:<\/p>\n<pre><code>$ sudo .\/check-config.sh\nwarning: \/proc\/config.gz does not exist, searching other paths for kernel config...\ninfo: reading kernel config from \/boot\/config-3.13.0-39-generic ...\nGenerally Necessary:\n- cgroup hierarchy: properly mounted [\/sys\/fs\/cgroup]\n- apparmor: enabled and tools installed\n- CONFIG_NAMESPACES: enabled\n- CONFIG_NET_NS: enabled\n- CONFIG_PID_NS: enabled\n- CONFIG_IPC_NS: enabled\n- CONFIG_UTS_NS: enabled\n- CONFIG_DEVPTS_MULTIPLE_INSTANCES: enabled\n- CONFIG_CGROUPS: enabled\n- CONFIG_CGROUP_CPUACCT: enabled\n- CONFIG_CGROUP_DEVICE: enabled\n- CONFIG_CGROUP_FREEZER: enabled\n- CONFIG_CGROUP_SCHED: enabled\n- CONFIG_MACVLAN: enabled\n- CONFIG_VETH: enabled\n- CONFIG_BRIDGE: enabled\n- CONFIG_NF_NAT_IPV4: enabled\n- CONFIG_IP_NF_FILTER: enabled\n- CONFIG_IP_NF_TARGET_MASQUERADE: enabled\n- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE: enabled\n- CONFIG_NETFILTER_XT_MATCH_CONNTRACK: enabled\n- CONFIG_NF_NAT: enabled\n- CONFIG_NF_NAT_NEEDED: enabled\nOptional Features:\n- CONFIG_MEMCG_SWAP: enabled\n- CONFIG_RESOURCE_COUNTERS: enabled\n- CONFIG_CGROUP_PERF: enabled\n- Storage Drivers:\n  - \"aufs\":\n    - CONFIG_AUFS_FS: enabled\n    - CONFIG_EXT4_FS_POSIX_ACL: enabled\n    - CONFIG_EXT4_FS_SECURITY: enabled\n  - \"btrfs\":\n    - CONFIG_BTRFS_FS: enabled\n  - \"devicemapper\":\n    - CONFIG_BLK_DEV_DM: enabled\n    - CONFIG_DM_THIN_PROVISIONING: enabled\n    - CONFIG_EXT4_FS: enabled\n    - CONFIG_EXT4_FS_POSIX_ACL: enabled\n    - CONFIG_EXT4_FS_SECURITY: enabled\n  - \"overlayfs\":\n    - CONFIG_OVERLAYFS_FS: enabled\n<\/code><\/pre>\n<p>If not running we can start the service and set it for auto start:<\/p>\n<pre><code>$ sudo service docker start\n$ sudo update-rc.d docker enable\n<\/code><\/pre>\n<p>After that we should see the default network bridge <code>docker0<\/code> and its network <code>172.17.0.0\/16<\/code> created by Docker.<\/p>\n<p>Something to have in mind, on Ubuntu-14.04 Docker installs both upstart and systemd init script so you need to decide which way you want to go. I personally decided to use upstart so I did:<\/p>\n<pre><code>$ sudo update-rc.d docker disable\n$ sudo start docker\n<\/code><\/pre>\n<p>to disable the systemd service and start Docker and leave upstart do its job on reboot. Also the latest Docker versions now utilize apparmor so installing this package is a prerequisite in<br \/>\nUbuntu and Debian.<\/p>\n<h2>Docker Images<\/h2>\n<p>The building base for Docker images is a file so called Dockerfile. Here we specify the building blocks of the image using specific Docker command language.  Check the <a href=\"http:\/\/docs.docker.com\/reference\/builder\/\">Docker documentation<\/a> for more details.<\/p>\n<p>We will create separate Docker image for each of our services like Tomcat, MongoDB, ElasticSearch etc. This means that to run a local Devtest environment on Docker one will need to run three containers and setup appropriate networking between them.<\/p>\n<h3>Elastic Search<\/h3>\n<p>This is going to be our ElasticSearch <code>Dockerfile<\/code>:<\/p>\n<pre><code>FROM ubuntu:14.04\nMAINTAINER Igor Cicimov &lt;igorc@encompasscorporation.com&gt;\nRUN apt-get -y update\nRUN apt-get install -y python-yaml python-jinja2 python-httplib2 python-keyczar python-paramiko python-setuptools python-pkg-resources python-pip git aptitude wget curl software-properties-common\nRUN apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/* \/tmp\/* \/var\/tmp\/*\nRUN git clone http:\/\/github.com\/ansible\/ansible.git \/tmp\/ansible\nWORKDIR \/tmp\/ansible\nRUN git submodule update --init --recursive\nENV PATH \/tmp\/ansible\/bin:\/sbin:\/usr\/sbin:\/usr\/bin:\/bin\nENV ANSIBLE_LIBRARY \/tmp\/ansible\/lib\nENV PYTHONPATH \/tmp\/ansible\/lib:$PYTHON_PATH\nRUN git clone https:\/\/&lt;my-user&gt;:&lt;my-password&gt;@github.com\/portlandrisk\/configuration-management.git \/tmp\/configuration-management\nADD elastic_search_main_tasks.yml \/tmp\/configuration-management\/roles\/elastic_search\/tasks\/main.yml\nADD inventory \/etc\/ansible\/hosts\nADD elastic_search.yml \/tmp\/configuration-management\/\nWORKDIR \/tmp\/configuration-management\nRUN ansible-playbook elastic_search.yml -c local --verbose\nWORKDIR \/root\nRUN rm -rf \/tmp\/configuration-management\nEXPOSE 22\nEXPOSE 9200\nEXPOSE 9300\nRUN echo \". \/lib\/lsb\/init-functions\" &gt;&gt; \/etc\/bash.bashrc\nRUN echo \"\/etc\/init.d\/elasticsearch start\" &gt;&gt; \/etc\/bash.bashrc\nENTRYPOINT [\"\/bin\/bash\"]\n<\/code><\/pre>\n<p>Here we specify everything related to the image starting from the Linux distribution and version, in this case we download and build on the official public Ubuntu-14.04 Docker image, Ansible integration, services to start when the image gets launched in a Docker container and the ports it will expose to the clients. Then we create two Ansible playbooks in the current working directory that will do all the installation and configuration job for us. The main playbook <code>elastic_search.yml<\/code>:<\/p>\n<pre><code>---\n- hosts: localhost\n  connection: local\n  gather_facts: true\n  vars_files:\n    - \"group_vars\/app_servers\"\n  roles:\n    - oracle_jdk\n    - elastic_search\n<\/code><\/pre>\n<p>and the tasks playbook attached elastic_search_main_tasks.yml. We gonna drop in our cloned repository in the image and run them during creation. To start the build we simply run:<\/p>\n<pre><code>$ sudo docker build --rm -t encompass\/elastic_search .\n<\/code><\/pre>\n<p>The <code>--rm<\/code> switch removes the intermediate containers upon successful build. Docker works in layers thus the containers build on top of the previous one (meaning for each instruction in the Dockerfile it starts a new container, executes the command, shuts down that container and removes it after committing it into a image that will be used for a new container in the next step) and we don&#8217;t want those left lying around. When finished running we will have a new Docker image tagged latest in the local encompass\/elastic_search repository:<\/p>\n<pre><code>$ sudo docker images\nREPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE\nencompass\/elastic_search   latest              68fac36afdb9        24 hours ago        1.735 GB\nubuntu                     14.04               5506de2b643b        3 weeks ago         197.8 MB\n<\/code><\/pre>\n<p>Apart our new image we also see the downloaded official Ubuntu image we based our build upon. We want to keep it so we don&#8217;t have to download it over and over again in the next builds. This is one nice feature that Docker caching provides.<\/p>\n<h3>MongoDB<\/h3>\n<p>I&#8217;ll just provide the files here since all needed has been said in the previous section.<\/p>\n<pre><code>FROM ubuntu:14.04\nMAINTAINER Igor Cicimov &lt;igorc@encompasscorporation.com&gt;\nRUN apt-get -y update\nRUN apt-get install -y python-yaml python-jinja2 python-httplib2 python-keyczar python-paramiko python-setuptools python-pkg-resources python-pip git aptitude wget curl software-properties-common\nRUN apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/* \/tmp\/* \/var\/tmp\/*\nRUN git clone http:\/\/github.com\/ansible\/ansible.git \/tmp\/ansible\nWORKDIR \/tmp\/ansible\nRUN git submodule update --init\nENV PATH \/tmp\/ansible\/bin:\/sbin:\/usr\/sbin:\/usr\/bin:\/bin\nENV ANSIBLE_LIBRARY \/tmp\/ansible\/lib\nENV PYTHONPATH \/tmp\/ansible\/lib:$PYTHON_PATH\nRUN git clone https:\/\/&lt;my-user&gt;:&lt;my-password&gt;@github.com\/portlandrisk\/configuration-management.git \/tmp\/configuration-management\nADD mongodb_main_tasks.yml \/tmp\/configuration-management\/roles\/mongo\/tasks\/main.yml\nADD inventory \/etc\/ansible\/hosts\nADD mongodb.yml \/tmp\/configuration-management\/\nWORKDIR \/tmp\/configuration-management\nRUN ansible-playbook mongodb.yml -c local --verbose\nWORKDIR \/root\nRUN rm -rf \/tmp\/configuration-management\nEXPOSE 22\nEXPOSE 27017\nEXPOSE 27018\nEXPOSE 28017\nEXPOSE 28018\nRUN echo \". \/lib\/lsb\/init-functions\" &gt;&gt; \/etc\/bash.bashrc\nRUN echo \"exec sudo -u mongodb \/usr\/bin\/mongod --config \/etc\/mongodb.conf --smallfiles --fork &amp;&gt;\/dev\/null &amp;\" &gt;&gt; \/etc\/bash.bashrc\nRUN echo \"exec sudo -u mongodb \/usr\/bin\/mongod --config \/etc\/mongodb_audit.conf --smallfiles --fork &amp;&gt;\/dev\/null &amp;\" &gt;&gt; \/etc\/bash.bashrc\nENTRYPOINT [\"\/bin\/bash\"]\n<\/code><\/pre>\n<p>and the main playbook <code>mongodb.yml<\/code>:<\/p>\n<pre><code>---\n- hosts: localhost\n  connection: local\n  gather_facts: true\n  vars_files:\n    - group_vars\/app_servers\n  roles:\n    - mongo\n<\/code><\/pre>\n<p>and the attached mongodb_main_tasks.yml playbook for the setup. Similar to the previous example we build our image:<\/p>\n<pre><code>$ sudo docker build --rm -t encompass\/mongodb .\n<\/code><\/pre>\n<p>But in this case we have some additional job to do. After starting a container with this initial image:<\/p>\n<pre><code>$ sudo docker run --name=\"MongoDB\" --rm -t -i encompass\/mongodb\n<\/code><\/pre>\n<p>which will also log us in, we need to run the following inside the container:<\/p>\n<pre><code>$ \/usr\/bin\/mongo \/tmp\/create-encompass-db-and-users.js\n$ \/usr\/bin\/mongo \/tmp\/create-audit-db-and-users.js\n$ for col in User Site SubscriptionType Account; do \/usr\/bin\/mongorestore --port 27017 --db encompass --username encompass --password password --collection $col --drop \/tmp\/${col}.collection\/encompass\/${col}.bson; done\n<\/code><\/pre>\n<p>to create our databases, users and collections. The files needed have been already placed under \/tmp during our image creation by Ansible but couldn&#8217;t be ran since of course no services can be started inside the image it self at that point. Now we need to commit this container in order to create our final image:<\/p>\n<pre><code>$ sudo docker commit 8111c11050c5 encompass\/mongodb:latest\n<\/code><\/pre>\n<p>where <code>8111c11050c5<\/code> is the container id we find by running:<\/p>\n<pre><code>$ sudo docker ps\n<\/code><\/pre>\n<p>and finding the one named MongoDB. After we exit from this container, it will be automatically deleted since we have started it with the <code>--rm<\/code> switch.<\/p>\n<h3>Tomcat<\/h3>\n<p>We follow the same procedure in this case too. We change the <code>Dockerfile<\/code> for tomcat configuration:<\/p>\n<pre><code>FROM ubuntu:14.04\nMAINTAINER Igor Cicimov &lt;igorc@encompasscorporation.com&gt;\nRUN apt-get -y update\nRUN apt-get install -y python-yaml python-jinja2 python-httplib2 python-keyczar python-paramiko python-setuptools python-pkg-resources python-pip git aptitude wget curl software-properties-common\nRUN apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/* \/tmp\/* \/var\/tmp\/*\nRUN git clone http:\/\/github.com\/ansible\/ansible.git \/tmp\/ansible\nWORKDIR \/tmp\/ansible\nRUN git submodule update --init --recursive\nENV PATH \/tmp\/ansible\/bin:\/sbin:\/usr\/sbin:\/usr\/bin:\/bin\nENV ANSIBLE_LIBRARY \/tmp\/ansible\/lib\nENV PYTHONPATH \/tmp\/ansible\/lib:$PYTHON_PATH\nRUN git clone https:\/\/&lt;my-user&gt;:&lt;my-password&gt;@github.com\/portlandrisk\/configuration-management.git \/tmp\/configuration-management\nADD tomcat7_main_tasks.yml \/tmp\/configuration-management\/roles\/tomcat7\/tasks\/main.yml\nADD inventory \/etc\/ansible\/hosts\nADD tomcat7.yml \/tmp\/configuration-management\/\nWORKDIR \/tmp\/configuration-management\nRUN ansible-playbook tomcat7.yml -c local --verbose\nWORKDIR \/root\nRUN rm -rf \/tmp\/configuration-management\n#EXPOSE 22 3000 27017 27018 28017 28018 443 8998 8999 9200 9300\nEXPOSE 22\nEXPOSE 80\nEXPOSE 443\nEXPOSE 8998\nEXPOSE 8999\nRUN echo \". \/lib\/lsb\/init-functions\" &gt;&gt; \/etc\/bash.bashrc\nRUN echo \"rm -rf \/var\/cache\/tomcat7\/*\" &gt;&gt; \/etc\/bash.bashrc\nRUN echo \"\/etc\/init.d\/tomcat7 start\" &gt;&gt; \/etc\/bash.bashrc\nENTRYPOINT [\"\/bin\/bash\"]\n<\/code><\/pre>\n<p>the main playbook <code>tomcat7.yml<\/code>:<\/p>\n<pre><code>---\n- hosts: localhost\n  connection: local\n  gather_facts: true\n  vars_files:\n    - \"group_vars\/app_servers\"\n  roles:\n    - oracle_jdk\n    - tomcat7\n<\/code><\/pre>\n<p>and the attached tomcat7_main_tasks.yml file. We run the build command with only these three files in the current working directory to build the Tomcat image:<\/p>\n<pre><code>$ sudo docker build --rm -t encompass\/tomcat7 .\n<\/code><\/pre>\n<p>At the end we have our three images built and ready to be used:<\/p>\n<pre><code>$ sudo docker images\nREPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE\nencompass\/tomcat7          latest              ad640bbc8e1e        About an hour ago   2.012 GB\nencompass\/mongodb          latest              60c7f5c41c5e        5 hours ago         2.985 GB\nencompass\/elastic_search   latest              68fac36afdb9        25 hours ago        1.735 GB\nubuntu                     14.04               5506de2b643b        3 weeks ago         197.8 MB\n<\/code><\/pre>\n<p>The next step is to create some containers.<\/p>\n<h2>Docker Containers<\/h2>\n<p>Creating containers from our images is fairly simple. This is how we do it, the <code>-d<\/code> switch send the process in the background:<\/p>\n<pre><code>$ sudo docker run -d --name=\"ElasticSearch\" -t -i encompass\/elastic_search:latest\n$ sudo docker run -d --name=\"MongoDB\" -t -i encompass\/mongodb:latest\n$ sudo docker run -d --name=\"Tomcat\" -t -i encompass\/tomcat7:latest\n<\/code><\/pre>\n<p>and there we have our containers up and running:<\/p>\n<pre><code>$ sudo docker ps\nCONTAINER ID        IMAGE                             COMMAND             CREATED             STATUS              PORTS                                                NAMES\n82b1f9d4d872        encompass\/tomcat7:latest          \"\/bin\/bash\"         4 hours ago         Up 4 hours          443\/tcp, 80\/tcp, 8998\/tcp, 8999\/tcp, 22\/tcp          Tomcat             \n78aeae57d011        encompass\/mongodb:latest          \"\/bin\/bash\"         7 hours ago         Up 7 hours          28017\/tcp, 28018\/tcp, 22\/tcp, 27017\/tcp, 27018\/tcp   MongoDB            \ne4e2bca92bce        encompass\/elastic_search:latest   \"\/bin\/bash\"         28 hours ago        Up 7 hours          22\/tcp, 9200\/tcp, 9300\/tcp                           ElasticSearch\n<\/code><\/pre>\n<p>We can stop and start them:<\/p>\n<pre><code>$ sudo docker stop 82b1f9d4d872\n$ sudo docker start 82b1f9d4d872\n<\/code><\/pre>\n<p>or attach them in case we want to do some work inside:<\/p>\n<pre><code>$ sudo docker attach 82b1f9d4d872\n<\/code><\/pre>\n<p>To detach from it we use the <code>Ctrl+P<\/code> followed by <code>Ctrl+Q<\/code> keyboard sequence. If we leave the container with exit command it will shut the container down as well. To completely remove a container we need to stop it first and then wipe it off using its id or name as target:<\/p>\n<pre><code>$ sudo docker rm [container-name|container-id]\n<\/code><\/pre>\n<p>To remove an image, first we need to make sure it is not in use by any container and then run:<\/p>\n<pre><code>$ sudo docker rmi [image-name|image-id]\n<\/code><\/pre>\n<p>We can always remove it forcefully if needed by using the <code>--f<\/code> switch in the above command.<\/p>\n<p>Another feature I like about Docker is the way we can dynamically dedicate resources for the containers on start up. For example:<\/p>\n<pre><code>$ sudo docker run --rm -c 512 --cpu 2 -m 512m -t -i encompass\/elastic_search:latest\n<\/code><\/pre>\n<p>will start the container and limit its resources to 2 CPU&#8217;s with 50% of their processing time and 512MB of RAM. We can even tell the container on which CPU&#8217;s we want it to run via <code>--cpuset<\/code> option, for example <code>--cpuset=0,2<\/code>.<\/p>\n<p>If we want our container to be started together with the docker service we can add <code>--restart always<\/code> option to the docker run command. That way we can make sure our container is constantly running even after docker or host restart.<\/p>\n<p>Since we have exposed some service ports inside our custom built images, now we can connect to them from the host after we find the IP address of our containers. For Tomcat one for example:<\/p>\n<pre><code>$ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' 82b1f9d4d872\n172.17.0.138\n\n$ telnet 172.17.0.138 443\nTrying 172.17.0.138...\nConnected to 172.17.0.138.\nEscape character is '^]'.\n^]\ntelnet&gt; quit\n\n$ openssl s_client -connect 172.17.0.138:443 -tls1_2\nCONNECTED(00000003)\ndepth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA\nverify error:num=19:self signed certificate in certificate chain\nverify return:0\n---\nCertificate chain\n 0 s:\/C=AU\/ST=New South Wales\/L=Sydney\/O=Encompass Corporation Pty Ltd\/CN=*.encompasshost.com\n   i:\/C=US\/O=DigiCert Inc\/CN=DigiCert Secure Server CA\n 1 s:\/C=US\/O=DigiCert Inc\/CN=DigiCert Secure Server CA\n   i:\/C=US\/O=DigiCert Inc\/OU=www.digicert.com\/CN=DigiCert Global Root CA\n 2 s:\/C=US\/O=DigiCert Inc\/OU=www.digicert.com\/CN=DigiCert Global Root CA\n   i:\/C=US\/O=DigiCert Inc\/OU=www.digicert.com\/CN=DigiCert Global Root CA\n---\nServer certificate\n...\n<\/code><\/pre>\n<h2>Docker Repository<\/h2>\n<p>Now that we have our images ready we need to make them available for the rest of the Encompass users. The simplest and fastest way is using the Docker Hub. I have created an account and a private repository for our images. Since the repository name is <code>[my -user]\/[my -repository]<\/code> I need to tag my images accordingly to be able to push them:<\/p>\n<pre>\n$ sudo docker tag encompass\/elastic_search:latest [my -user]\/[my -repository]:elastic_search\n$ sudo docker tag encompass\/mongodb:latest [my -user]\/[my -repository]:mongodb\n$ sudo docker tag encompass\/tomcat7:latest [my -user]\/[my -repository]:tomcat7\n<\/pre>\n<p>Now just need to run:<\/p>\n<pre>\n$ sudo docker login\n$ sudo docker push [my -user]\/[my -repository]:elastic_search\n$ sudo docker push [my -user]\/[my -repository]:mongodb\n$ sudo docker push [my -user]\/[my -repository]:tomcat7\n<\/pre>\n<p>and the images will appear in the Hub repository with tags of <code>elastic_search<\/code>, <code>mongodb<\/code> and <code>tomcat7<\/code>.<\/p>\n<h2>Converting Docker Container into Image<\/h2>\n<p>Lets say we have a new version of our app we have deployed into our local Tomcat container [Deploying Encompass In Docker Containers]({{ site.baseurl }}{% post_url 2015-07-09-Deploying-Encompass-in-Docker-containers %}). Or we have made some important configuration changes to our local instance that we want to make official and propagate to the rest of the users. After we have finished with our changes, all we need to do is commit the container into new image tagging it as appropriate and push that image to our private Docker repository. For example if our Tomcat container has an id of <code>e4e2bca92bce<\/code>:<\/p>\n<pre>\n$ sudo docker stop e4e2bca92bce\n$ sudo docker commit e4e2bca92bce [my -user]\/[my -repository]:NovemberRelease\n$ sudo docker push [my -user]\/[my -repository]:NovemberRelease\n$ sudo docker start e4e2bca92bce\n<\/pre>\n<p>Now the rest of the users can pull this new version of the image, shutdown their old Tomcat container (optional) and start a new one using this new image:<\/p>\n<pre>\n$ sudo docker pull [my -user]\/[my -repository]:NovemberRelease\n$ sudo docker run -d --name=\"Tomcat\" --link MongoDB:db --link ElasticSearch:es -p 443:443 -v \/opt\/encompass\/deploy:\/opt\/encompass\/deploy -t -i [my -user]\/[my -repository]:NovemberRelease\n<\/pre>\n<p>In this way we can have more than one version of our application running locally. We can keep the initial version running and start a new one in parallel and both will share same MongoDB and ElasticSearch resources. Of course, if we want we can produce separate images for these services as well similar to what we have done with Tomcat and run two completely separate stacks in parallel.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Due to ever rising popularity of Docker this page will provide a walk through process of building custom Encompass Docker images and creating containers. The image configuration will be executed with our existing Ansible repository. We will store this images&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,14,13],"tags":[],"class_list":["post-198","post","type-post","status-publish","format-standard","hentry","category-devops","category-docker","category-virtualization"],"_links":{"self":[{"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=198"}],"version-history":[{"count":4,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/198\/revisions"}],"predecessor-version":[{"id":202,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/198\/revisions\/202"}],"wp:attachment":[{"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/icicimov.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}