What is Docker?
Docker is a platform.
Docker runs natively on Linux or on OS X and Windows through a helper application called boot2docker that creates a Linux Virtual Machine, by using only RAM, to run Docker.
Docker‘s main goal is to allow you to ship distributed applications, that you’ve created previously, by running them as isolated process on what is known as a container, thus it avoids the need of Virtual Machines that implies a resources saving in the involved machines. The isolation also allows to run several containers simultaneously.
So, Docker is an open platform for developing, shipping, and running applications.
The key point is that you can separate your application from the infrastructure and also treats the infrastructure as an application. Everything can be packaged, distributed and deployed anywhere and quickly. It’s said that Docker eliminates the friction between development, QA, and production environments.
Docker has two major components:
- Docker, the container virtualization platform, that has a daemon running on a host server and a client (the docker binary) to talk to the Docker daemon.
- Docker Hub, the SaaS platform for sharing and managing Docker containers.
Docker concepts
- Image (build component of Docker): a Docker environment template, it consists in files (a copy of what is expected to contain) and metadata (information such as environment variables, port mappings and so on) and it has a name (“ubuntu”, for instance)
- Registry (distribution component of Docker): a public or private store that holds images. The public Docker registry is called Docker Hub.
- Container (run component of Docker): a running instance of a Docker image. It’s created from a Docker image, and it can be run, started, stopped, moved, and deleted. Each container is an isolated and secure application platform.
How Does Docker work?
An image is a serie of layers that are combined into a single image by Docker using union file systems (UnionFS, a file system service that allows files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system)
From a base image, you can add and modify additional layers and there’s no need of rebuilding the entire image if there is a change, you only need replace the added or updated layer.
A container is built from an image, that is read-only. For running the container, Docker adds a read-write layer on top of the image (using UnionFS) and then allocates a network/bridge interface, an IP address, and finally, executes the specified process and captures input and provides output.
The container is isolated thanks to a technology called namespaces (Namespace isolation, where groups of processes are separated such that they cannot “see” resources in other groups)
Docker use these namespaces:
- The pid namespace, for process isolation.
- The net namespace, for managing network interfaces.
- The ipc namespace, for Inter-Process Communication.
- The mnt namespace, for managing mount-points.
- The uts namespace, for changing the hostname.
In order to achieve isolation on running application, Docker uses another technology called control groups (cgroups, it limits, accounts for, and isolates the resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes)
Installing Docker
I’m going to use Ubuntu (as Sheldon Cooper said, my favorite Linux-based operating system)
There are three packages available, two of them from Ubuntu, an older KDE3/GNOME2 called docker (warning, this is the suggested package when you try docker version before having installed: “The program ‘docker’ is currently not installed. You can install it by typing: sudo apt-get install docker”) and a newer called docker.io, that is not the most recent Docker release. The third one is a PPA (Personal Package Archives for Ubuntu) for Docker and it’s called lxc-docker.
If you don’t want extra repositories and you don’t want the latest version, just install docker.io (I recommend you to enable tab-completion of Docker commands in BASH if you install it):
1 2 3 |
$ sudo apt-get update $ sudo apt-get install docker.io $ source /etc/bash_completion.d/docker.io |
To validate the installation, type:
1 2 3 4 5 6 7 8 9 10 |
$ sudo docker version Client version: 1.0.1 Client API version: 1.12 Go version (client): go1.2.1 Git commit (client): 990021a Server version: 1.0.1 Server API version: 1.12 Go version (server): go1.2.1 Git commit (server): 990021a $ |
You need to use sudo because the docker daemon always runs as the root user, that’s because the docker daemon binds to a Unix socket (instead of a TCP port, as it happened until version 0.5.2). By default that Unix socket is owned by the user root, so you need to use the docker command with sudo. You can solve it by giving non-root access to Docker or, even better, you can create a docker group and add users to it.
Otherwise, if you run docker without sudo you will obtain this error message:
1 2 3 4 5 6 7 |
$ docker version Client version: 1.0.1 Client API version: 1.12 Go version (client): go1.2.1 Git commit (client): 990021a 2015/03/20 11:40:30 Get http:///var/run/docker.sock/v1.12/version: dial unix /var/run/docker.sock: permission denied $ |
In order to have the latest version, use the lxc-docker package, that is the one maintained by Docker itself.
There is a script to install the Docker package on Ubuntu, but I’d rather to do it manually. But you can try with:
1 |
$ curl -sSL https://get.docker.com/ubuntu/ | sudo sh |
To install lxc-docker, your APT system have to deal with https (you can if the file /usr/lib/apt/methods/https exists, it you don’t have it, install the apt-transport-https package)
Then, just add the Docker repository key to the local keychain, and to the apt sources list. Finally, update and install the lxc-docker package:
1 2 3 4 |
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 $ sudo sh -c "echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list" $ sudo apt-get update $ sudo apt-get install lxc-docker |
Now we have the last version:
1 2 3 4 5 6 7 8 9 10 11 |
$ sudo docker version Client version: 1.5.0 Client API version: 1.17 Go version (client): go1.4.1 Git commit (client): a8a31ef OS/Arch (client): linux/amd64 Server version: 1.5.0 Server API version: 1.17 Go version (server): go1.4.1 Git commit (server): a8a31ef $ |
And we can run the basic example, that downloads the ubuntu image, and then start bash in a container. When you’re done, type exit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ sudo docker run -i -t ubuntu /bin/bash Unable to find image 'ubuntu:latest' locally 511136ea3c5a: Pull complete f3c84ac3a053: Pull complete 511136ea3c5a: Download complete f3c84ac3a053: Download complete a1a958a24818: Download complete 9fec74352904: Download complete d0955f21bf24: Download complete Status: Downloaded newer image for ubuntu:latest root@0f5e5a64c583:/# ls bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr root@0f5e5a64c583:/# exit exit $ |
Having said that, Docker has changed the instructions for Installing Docker on Ubuntu… today!
It seems easier, but I don’t like it very much. If you have wget installed, you can get the latest Docker package with:
1 |
$ wget -qO- https://get.docker.com/ | sh |
It prompts for the password and then it downloads and installs… the lxc-docker package.
And then, verify the installation with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ sudo docker run hello-world [sudo] password for Javier: Unable to find image 'hello-world:latest' locally 31cbccb51277: Pull complete e45a5af57b00: Pull complete 511136ea3c5a: Already exists hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. Status: Downloaded newer image for hello-world:latest Hello from Docker. This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (Assuming it was not already locally available.) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash For more examples and ideas, visit: http://docs.docker.com/userguide/ $ |
Using Docker
Running applications inside containers
Docker allows you to run applications inside containers with the command docker run.
The command docker run creates a new container from the image name that you specify (the mandatory parameter for run) and then runs the command in it by performing these steps: Docker looks for the image in this computer, if it isn’t installed yet, Docker searches the image at Docker Hub to download it and install it. Once the image is installed, Docker creates a new container and starts the program.
We’ve seen above one example:
1 |
$ sudo docker run -t -i ubuntu:14.04.2 /bin/bash |
It creates a container from the Official Ubuntu base image (tag 14.04.2) and then it runs a Bash shell command, with a terminal assigned (flag -t), and grabs the standard in of the container(flag -i)
For executing in the background (or daemonized), use the -d flag:
1 2 |
$ sudo docker run -d --name="Javier" ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" e84ae64138881b9eaf6ac743c6f0076cfc414f017daef9e59c3d2e1d591eb7b9 |
Here, the command will run forever. Besides, I have assigned a name to the container (OK, my very name, some egocentricity here) to easily discover it later (Docker automatically names any containers that you start, but I’d rather to specify the name by myself). Furthermore, Docker returns the container ID (e84ae6413888…).
You can find both the ID and the name when listing containers with the command docker ps (flag -a to show all regardless they are running or not)
1 2 3 4 |
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e84ae6413888 ubuntu:14.04 "/bin/sh -c 'while t 5 days ago Up 2 minutes Javier $ |
The ports in the container can be exposed randomly with the -P flag or manually with -p. In any case, you can see in the column PORTS of the docker ps command or with the docker port command. Let’s see an example with a sample web application image.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ sudo docker run -d -P training/webapp python app.py Unable to find image 'training/webapp:latest' locally Pulling repository training/webapp 31fa814ba25a: Download complete 511136ea3c5a: Download complete f10ebce2c0e1: Download complete 82cdea7ab5b5: Download complete 5dbd9cb5a02f: Download complete 74fe38d11401: Download complete 64523f641a05: Download complete 0e2afc9aad6e: Download complete e8fc7643ceb1: Download complete 733b0e3dbcee: Download complete a1feb043c441: Download complete e12923494f6a: Download complete a15f98c46748: Download complete Status: Downloaded newer image for training/webapp:latest a03ec94ea8087789d605ca91d6689d8026e7806e9138b8b9b7ed7f5a1295db85 $ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a03ec94ea808 training/webapp:latest "python app.py" 25 seconds ago Up 24 seconds 0.0.0.0:49153->5000/tcp happy_pare $ sudo docker port happy_pare 5000/tcp -> 0.0.0.0:49153 $ curl http://localhost:49153 Hello world! $ |
This means that you can access the application running in the container by using the port 49153 locally.
To manage the container, you can use the next commands:
- docker logs to see the standard output of a container (-f to view the new additions, press Ctrl+C to exit)
- docker top to see the process in the container.
- docker inspect to see configuration and status information about a container.
- docker stop/kill to stop or kills (respectively) a running container.
- docker start to restart a stopped container (remember the command docker ps -a).
- docker rm to remove a container.
- docker version to see the current version of the program, its programming language (Go) and so on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
$ sudo docker logs happy_pare * Running on http://0.0.0.0:5000/ 172.17.42.1 - - [31/Mar/2015 09:51:38] "GET / HTTP/1.1" 200 - $ sudo docker stop happy_pare happy_pare $ sudo docker start happy_pare happy_pare $ sudo docker kill happy_pare happy_pare $ sudo docker rm happy_pare happy_pare $ sudo docker top happy_pare UID PID PPID C STIME TTY TIME CMD root 8580 1372 0 12:00 ? 00:00:00 python app.py $ sudo docker inspect hungry_kirch [{ "AppArmorProfile": "", "Args": [ "app.py" ], "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "python", "app.py" ], "CpuShares": 0, "Cpuset": "", "Domainname": "", "Entrypoint": null, "Env": [ "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "ExposedPorts": { "5000/tcp": {} }, "Hostname": "468cd593eada", "Image": "training/webapp", "MacAddress": "", "Memory": 0, "MemorySwap": 0, "NetworkDisabled": false, "OnBuild": null, "OpenStdin": false, "PortSpecs": null, "StdinOnce": false, "Tty": false, "User": "", "Volumes": null, "WorkingDir": "/opt/webapp" }, "Created": "2015-03-31T10:00:32.697111567Z", "Driver": "aufs", "ExecDriver": "native-0.2", "ExecIDs": null, "HostConfig": { "Binds": null, "CapAdd": null, "CapDrop": null, "ContainerIDFile": "", "Devices": [], "Dns": null, "DnsSearch": null, "ExtraHosts": null, "IpcMode": "", "Links": null, "LxcConf": [], "NetworkMode": "bridge", "PidMode": "", "PortBindings": {}, "Privileged": false, "PublishAllPorts": true, "ReadonlyRootfs": false, "RestartPolicy": { "MaximumRetryCount": 0, "Name": "" }, "SecurityOpt": null, "VolumesFrom": null }, "HostnamePath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/hostname", "HostsPath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/hosts", "Id": "468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3", "Image": "31fa814ba25ae3426f8710df7a48d567d4022527ef2c14964bb8bc45e653417c", "MountLabel": "", "Name": "/hungry_kirch", "NetworkSettings": { "Bridge": "docker0", "Gateway": "172.17.42.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.10", "IPPrefixLen": 16, "IPv6Gateway": "", "LinkLocalIPv6Address": "fe80::42:acff:fe11:a", "LinkLocalIPv6PrefixLen": 64, "MacAddress": "02:42:ac:11:00:0a", "PortMapping": null, "Ports": { "5000/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "49155" } ] } }, "Path": "python", "ProcessLabel": "", "ResolvConfPath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/resolv.conf", "RestartCount": 0, "State": { "Error": "", "ExitCode": 0, "FinishedAt": "0001-01-01T00:00:00Z", "OOMKilled": false, "Paused": false, "Pid": 8580, "Restarting": false, "Running": true, "StartedAt": "2015-03-31T10:00:32.898205331Z" }, "Volumes": {}, "VolumesRW": {} } ] $ |
Working with Docker Images
As we have explained, Docker runs container by using images that are either installed in your system or exists at Docker Hub (in order to download it and install in your system)
You can see what images are already installed with the docker images command.
1 2 3 4 5 6 7 8 9 |
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu trusty-20150320 d0955f21bf24 11 days ago 188.3 MB ubuntu 14.04 d0955f21bf24 11 days ago 188.3 MB ubuntu 14.04.2 d0955f21bf24 11 days ago 188.3 MB ubuntu latest d0955f21bf24 11 days ago 188.3 MB ubuntu trusty d0955f21bf24 11 days ago 188.3 MB training/webapp latest 31fa814ba25a 10 months ago 278.8 MB $ |
If you want to manually install an image before running it, you can use the docker pull command for images that you can find at Docker Hub or with the command docker search.
As a curiosity, if you look for images at Docker Hub, you can find Official repos, for instance, the Java OFFICIAL REPO.
You can add a new name to the image with the docker tag.
If you want to remove an image, you can do so with the docker rmi command.
A note about the official images
The images and relevant files are maintained at GitHub by an organization called docker-library (Docker is open source, and it’s maintained at GitHub by an organization called Docker, that has several repositories, including the one for docker).
The official images exist in a repository, Docker Official Images, that contains a folder for the library definitions, for instance, the one for java.
The image packages are also maintained by docker-library in each corresponding repository, for instance, the Docker Official Image packaging for Java (openJDK)
It’s worth to mention it because there is another organization at GitHub called (Trusted Automated Docker Builds) that has repositories for several Docker builds, for instance, the one for Java, that includes an image for Oracle Java 8 JDK (that I was looking for)
Creating your own images
There are two ways for updating and creating images.
- Run a container from an image (docker run), then update it, and finally commit the results to an image, with the docker commit command.
- Use a Dockerfile to create an image.
When you’re done, you can push the created image to Docker Hub with the docker push command.
Finally, you can remove images with the docker rmi command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
$ sudo docker run -t -i ubuntu:latest /bin/bash root@98bec5327540:/# sudo apt-get install --reinstall software-properties-common root@98bec5327540:/# sudo add-apt-repository ppa:webupd8team/java root@98bec5327540:/# sudo apt-get update root@98bec5327540:/# sudo apt-get install oracle-java8-installer root@98bec5327540:/# sudo apt-get install nano root@98bec5327540:/# wget http://apache.rediris.es/maven/maven-3/3.3.1/binaries/apache-maven-3.3.1-bin.tar.gz root@98bec5327540:/# tar -xvf apache-maven-3.3.1-bin.tar.gz root@98bec5327540:/# cp -r apache-maven-3.3.1 /usr/local/apache-maven root@98bec5327540:/# sudo nano /etc/environment PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/apache-maven/bin" JAVA_HOME="/usr/lib/jvm/java-8-oracle" MAVEN_OPTS="-Xms256m -Xmx512m" root@98bec5327540:/# source /etc/environment root@98bec5327540:/# echo $JAVA_HOME /usr/lib/jvm/java-8-oracle root@98bec5327540:/# java -version java version "1.8.0_40" Java(TM) SE Runtime Environment (build 1.8.0_40-b25) Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode) root@98bec5327540:/# mvn -version Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00) Maven home: /usr/local/apache-maven Java version: 1.8.0_40, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-8-oracle/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix" root@98bec5327540:/# exit $ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 98bec5327540 ubuntu:14.04 "/bin/bash" 47 minutes ago Exited (0) 4 minutes ago determined_carson 468cd593eada training/webapp:latest "python app.py" 2 hours ago Exited (137) 2 minutes ago hungry_kirch e84ae6413888 ubuntu:14.04 "/bin/sh -c 'while t 5 days ago Exited (137) 3 hours ago Javier 0f5e5a64c583 ubuntu:14.04 "/bin/bash" 11 days ago Exited (0) 11 days ago dreamy_hopper $ sudo docker commit -m "Ubuntu latest (14.04) with Oracle Java 8 JDK and Apache Maven 3.3.1 (and nano editor)" -a "Javier Beneito Barquero" 98bec5327540 jbbarquero/ubuntu-java8_oracle-maven e262639379c46afa53eca74de9df9bd2f81e0ab7839a3472cafb67d7e199d85e $ $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE jbbarquero/ubuntu-java8_oracle-maven latest e262639379c4 56 seconds ago 828 MB ubuntu 14.04 d0955f21bf24 11 days ago 188.3 MB ubuntu 14.04.2 d0955f21bf24 11 days ago 188.3 MB ubuntu latest d0955f21bf24 11 days ago 188.3 MB ubuntu trusty d0955f21bf24 11 days ago 188.3 MB ubuntu trusty-20150320 d0955f21bf24 11 days ago 188.3 MB centos latest 88f9454e60dd 3 weeks ago 210 MB hello-world latest e45a5af57b00 12 weeks ago 910 B training/webapp latest 31fa814ba25a 10 months ago 278.8 MB $ sudo docker tag jbbarquero/ubuntu-java8_oracle-maven my-java8 $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE jbbarquero/ubuntu-java8_oracle-maven latest e262639379c4 About a minute ago 828 MB my-java8 latest e262639379c4 About a minute ago 828 MB ubuntu trusty-20150320 d0955f21bf24 11 days ago 188.3 MB ubuntu 14.04 d0955f21bf24 11 days ago 188.3 MB ubuntu 14.04.2 d0955f21bf24 11 days ago 188.3 MB ubuntu latest d0955f21bf24 11 days ago 188.3 MB ubuntu trusty d0955f21bf24 11 days ago 188.3 MB centos latest 88f9454e60dd 3 weeks ago 210 MB hello-world latest e45a5af57b00 12 weeks ago 910 B training/webapp latest 31fa814ba25a 10 months ago 278.8 MB $ sudo docker run -t -i my-java8 /bin/bash root@da1045b88138:/# mvn -version Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00) Maven home: /usr/local/apache-maven Java version: 1.8.0_40, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-8-oracle/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix" root@da1045b88138:/# exit exit $ $ sudo docker push jbbarquero/ubuntu-java8_oracle-maven The push refers to a repository [jbbarquero/ubuntu-java8_oracle-maven] (len: 1) Sending image list Please login prior to push: Username: jbbarquero Password: Email: jbbarquero@gmail.com Login Succeeded The push refers to a repository [jbbarquero/ubuntu-java8_oracle-maven] (len: 1) Sending image list Pushing repository jbbarquero/ubuntu-java8_oracle-maven (1 tags) 511136ea3c5a: Image already pushed, skipping f3c84ac3a053: Image already pushed, skipping a1a958a24818: Image already pushed, skipping 9fec74352904: Image already pushed, skipping d0955f21bf24: Image already pushed, skipping e262639379c4: Image successfully pushed Pushing tag for rev [e262639379c4] on {https://cdn-registry-1.docker.io/v1/repositories/jbbarquero/ubuntu-java8_oracle-maven/tags/latest} $ |
You can find this image at jbbarquero / ubuntu-java8_oracle-maven
How to write a Dockerfile is out of the bounds of this first post, but I can create a very basic one. Just for fun.
Having this Dockerfile:
1 2 3 4 |
# This is a comment FROM jbbarquero/ubuntu-java8_oracle-maven MAINTAINER Javier Beneito Barquero <jbbarquero@gmail.com> RUN apt-get update && apt-get install -y git |
Just build it (and then push it)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$ sudo docker build -t jbbarquero/ubuntu-java8_oracle-maven-git . Sending build context to Docker daemon 2.048 kB Sending build context to Docker daemon Step 0 : FROM jbbarquero/ubuntu-java8_oracle-maven ---> e262639379c4 Step 1 : MAINTAINER Javier Beneito Barquero <jbbarquero@gmail.com> ---> Running in d1be5fc2ed6e ---> 162fdb8b3a3d Removing intermediate container d1be5fc2ed6e Step 2 : RUN apt-get update && apt-get install -y git ---> Running in b7c2cf318638 ... Lot of installation messages here ---> f63b88cf14ab Removing intermediate container b7c2cf318638 Successfully built f63b88cf14ab $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE jbbarquero/ubuntu-java8_oracle-maven-git latest f63b88cf14ab 17 seconds ago 876.5 MB ... $ sudo docker run -t -i jbbarquero/ubuntu-java8_oracle-maven-git /bin/bash root@bb9caa298372:/# git --version git version 1.9.1 root@bb9caa298372:/# mvn -version Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00) Maven home: /usr/local/apache-maven Java version: 1.8.0_40, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-8-oracle/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix" root@bb9caa298372:/# exit exit |
The new image can be found in Docker Hub, find it at jbbarquero / ubuntu-java8_oracle-maven-git.
Closing words
That’s enough for now. There are a couple of interesting topics, but we’ll leave for another time:
- Linking Containers, for sending information between containers in Docker.
- Data in containers, for managing data volumes.
Resources
- Docker official documentation
- Docker 10-minute tutorial
- Docker installation: Ubuntu
- Docker in Action. By Jeff Nickoloff (Manning)
- Docker in Practice. By Ian Miell and Aidan Hobson Sayers (Manning)
- Install oracle java 8 in ubuntu via ppa repository [jdk8]
- How to add a PPA on a server?
- Nano at Ubuntu
- Download Apache Maven 3.3.1
Post scríptum
When re-starting the container jbbarquero/ubuntu-java8_oracle-maven, source /etc/environment is not called, so the values that I wrote there are not applied. For solving this issue, I edited /etc/bash.bashrc and I put there the environment variables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
root@98bec5327540:/# sudo nano /etc/bash.bashrc $ sudo docker start -i 98bec5327540 root@98bec5327540:/# sudo nano /etc/bash.bashrc JAVA_HOME="/usr/lib/jvm/java-8-oracle" export JAVA_HOME M2_HOME=/usr/local/apache-maven export M2_HOME M2=$M2_HOME/bin export M2 PATH=$PATH:$JAVA_HOME PATH=$PATH:$M2 export PATH root@98bec5327540:/# exit |
Maybe a Dockerfile is a better idea to create containers with environment variables using ENV.
so the values that I wrote there