Docker tutorials 3: creating an image with a Dockerfile

We will do the same creation process as in tutorial 1 by using a Dockerfile.

By using any editor, let’s create in our working directory in the host machine a file named Dockerfile with the following content:

FROM ubuntu:latest
MAINTAINER myname <myname@mydomain.com>
RUN apt-get update
RUN apt-get -y upgrade
# By default, simply start a shell
CMD /bin/bash

Let us now run docker on the Dockerfile:

docker build -t myname:myLinux2 --rm=true .

A verbose output will follow.

Note:

  • myname:myLinux2 is the name of the created image.
  • –rm=true will remove intermediate containers created along the process.

We can now check that the image has been created:

docker images
REPOSITORY                     TAG                 IMAGE ID           CREATED             SIZE
myname                        myLinux2           50ee9e4f504d       13 minutes ago     215.9 MB

let’s start the image, running the default command and attaching the terminal:

docker run -it myname:myLinux2
#

Alternatively, we could have started the image, running an alternate command and attaching the terminal:

docker run -it myname:myLinux2 /bin/ls
bin   dev home lib64  mnt proc run  srv tmp var
boot etc lib media    opt root sbin sys usr

We get back to the host machine, since after running ls the docker machine has finishes

References:

Docker build:

Tagged with:
Posted in Docker

Docker tutorials 2: managing containers

As we have seen in Tutorial 1, we can check which containers are alive

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Nothing alive is in there. We then look for “sleeping” docker machines:

docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3583bb668676 ubuntu:latest "bash" 23 minutes ago Exited (0) 7 minutes ago myLinux

We can refer to the container either by name (myLinux) or by id (3583bb668676). If we did not assigna a name, there will by some ronfdomly generated one. The container can be renamed:

docker rename myLinux newName

or

docker rename 3583bb668676 newName

We can stop a running container, putting it to sleep

docker stop [ID|name]

We can resume the “sleeping” docker machines, and connect to it
docker start myLinux
docker attach myLinux
ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

We can get rid of the “sleeping” docker machine:
docker rm [ID|name]

Posted in Docker, Uncategorized

Docker tutorials 1: example of creating a linux box into docker

Note:

  • We’ll call “docker machine” the environment we create inside docker, which will look like another linux box we can control. Later on, when we get familiar with the idea, we’ll also call it “the container”.
  • Red lines are run on the host machine shell, blue line are run inside the docker machine. The output (from wherever it comes) is shown in green

1) Create a linux base, update it and install apache on it

docker run --name myLinux -it ubuntu:latest bash
apt-get update
apt-get -y upgrade
ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
^D

note: the ^D exits from the shell in the docker environment, and goes back to the host shell.

2) let’s verify that the docker machine is sleeping.

We first look for active docker machines:

docker ps
CONTAINER ID       IMAGE                         COMMAND                 CREATED             STATUS                     PORTS                                          NAMES

Nothing alive is in there. We then look for “sleeping” docker machines:

docker ps -a

CONTAINER ID       IMAGE                         COMMAND                 CREATED             STATUS                     PORTS                                          NAMES
3583bb668676       ubuntu:latest                 "bash"                   23 minutes ago     Exited (0) 7 minutes ago                                                    myLinux

3a) Let us resume the “sleeping” docker machines
docker attach myLinux
ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

3b) Alternatively, if we want to get rid of the “sleeping” docker machine we would user either its id or its name:
docker rm 3583bb668676
or
docker rm ubuntu:latest

Posted in Docker, Uncategorized

Docker Tutorials: Introduction

Docker is a great solution to the several problems,  such as the one of porting code and executables, and the one on installing software.

Docker logo

Docker logo

When we install software, we need a suitable environment. Just to make an example, some web apps need to have a certain version of php, others a different one. Configuring a machine with multiple versions of something (e.g. php)  may be feasible but complex. Moreover, sometimes we need to install certain supporting software just to test an app, that we later decide to drop: we are left with the now unnecessary stuff we’ve installed, or with the duty to correctly uninstall it.

When we port software to a different platform, we typically encounter a number of difficulties. A Java application may need a certain version of the APIs, and we need to make sure that our customer has installed it. Sure, we can include the java distribution in the jar, but resolving dependencies is not always that straightforward.

The Docker idea is close to the virtualization concept: we can create a virtual machine, and in that create the suitable environment for our app, and install it there.  Conceptually simple. However, that is not really virtualization, as Docker actually runs by reusing the kernel of the host machine – provided that is a Linux. If it is not, then there actually is a single VM running in the host, in the VM runs (only once) the Docker infrastructure that can host a number of “virtual environments” which take the form of Linux machines, and which are called “containers”. On the Mac, the docker distribution includes a VirtualBox VM which is automatically installed and run when needed. This is transparent, but has some implications (especially when working with the network layer).

Where do you start from to learn docker?

If you’re a Mac user, the right place is in the official site.

Why yet another tutorial?

There are a number of good Docker tutorials out there, especially those in the official site: the three videos (one hour each) are an excellent way to get oriented in the docker world. So why other tutorial?

Well, because not everything is immediately easy and straightforward. For instance, I had some difficulties in understanding how to install and deploy Apache in a container. Sure, I could have downloaded a ready-made image, but that would not have helped me understanding – and if you do not understand, the first problem you encounter is going to knock you out.

So I developed step-by-step examples which can be easily replicated, providing a guided learning path.

Here is the list:

  1. EXAMPLE OF CREATING A LINUX BOX INTO DOCKER
  2. MANAGING DOCKER CONTAINERS
  3. CREATING A LINUX BOX INTO DOCKER WITH A DOCKERFILE
  4. DOCKER IMAGES MANAGEMENT
  5. SHARING PART OF THE FILE SYSTEM WITH DOCKER
  6. INSTALLING APACHE2 ON DOCKER (ON A MAC) – PART 1
  7. INSTALLING APACHE2 ON DOCKER (ON A MAC) – PART 2: WRITING A Dockerfile

The tutorials will be made available over the next few days.

Tagged with: , ,
Posted in Docker

Interesting hidden apps in Mac OS-X

Well, we know that the Mac has a lot of hidden tricks and goodies. I just accidentally discovered that it has a some hidden interesting apps. They are in

/System/Library/CoreServices/Applications

One is “Network Utility”, a GUI front-end to some network commands, which can be launched from  Wireless Diagnosis as we reported in the previous note – but now that we know where it is we can dock it.

Another one is great: “Screen Sharing” allows you to take over another mac, and interact remotely with it. It seems to be much more responsive than  VNC!

The other ones are less impressive to me, but maybe I did not yet explore them deeply enough. They are:

  • Archive Utility.app – the app to compress/uncompress files callable from the Finder “File” menu
  • Directory Utility.app – an app to interact with directory services, such as LDAP
  • Feedback Assistant.app – to give feeback on beta Apple beta software
  • RAID Utility.app – to manage RAID devices
  • System Image Utility.app – an app to remotely install Mac-Os on other Macs on the local network
  • Wireless Diagnostics.app – the well-known app which can be launched in case of network troubles

 

Posted in Admin, Apps, Utilities

Quickly getting more info on your wireless connection in OS-X

If you option-click the Wireless icon on the menu bar, you get a lot of interesting info, such as your IP, router IP, reachability of Internet, channel, security type, signal strength and more.

From there, you can also start the probably familiar Wireless Diagnosis app. What I never noticed until now, is that Wireless Diagnosis has a menu,and from there, under “Open external tools”, you can launch “Network Utility”, which is essentially a front end to well known commands such as netstat, traceroute etc. Maybe not an essential tool, but a quick way to explore your network.

Posted in Apps, Utilities

Accessing Resources from java, and in particular from a jar

Using a resources bundle is a way to externalize code dependencies from text, images or other type of resources. As far as I know, it was pioneered by the Mac OS design, back in 1984. It allows changing elements in an app (for instance graphics and text) without recompiling. It is uses to a large extent in Android, but since the Java  origin the functionality was there.

Accessing resources in Java is generally not difficult. However, doing it in a way that works when launching the App from inside the IDE (say Netbeans), from a command line using java and using java -jar may end up into troubles.

On Stackoverflow there are many questions regarding this issue, but I did not find yet a convincing and exhaustive response. One of teh clearest explanations, with a working demo, is presente by mykong on his web site. Unfortunately, it does not work in a jar…

So let’s try to clear the ground.

The first issue is: where should resources be placed?

They should be in your src directory, where the package directory for the source code is. In some IDE, the src directory contains a main directory which contains the root of the package: in that case also the resources directory should go there (see mykong example).

We show the file hierarchy for a Netbeans project:

FIle system view of the project

File system view of the project

In this case, the ResourceAccess java class is in package it.unitn.resourceaccess.

The resources we want to use are a file called text.txt, which will contain some text lines, and camera-photo.png which contain an image. We’ve put them into resources/file and resources/img into the src directory (the used names are arbitrary, as long as in our code we refer correctly to them).

The resulting Netbeans project view is the following:

Project tree in Netbeans

Project tree in Netbeans

Now let’s try to access these resources from our code using the Java API. There is the getResource() method in the Class class, which returns an URL, so it seems quite natural to use it:
URL u=getClass().getResource("/resources/file/test.txt");
File f=new File(u.getFile());

It works if we launch our main class using the command line “java it.unitn.resourceacces.ResourceAccess”, but sadly it does not work if we launch the jar (which we can find in the dist directory in our project): in such case the getFile method called on the URL returns null.

If we look at the URL, the problem is clear: it turns to be:

/path/to/the/jar/ResourceAccess.jar!resources/file/test.txt

The problem is and that the file we want to access is not visible in the file system, but is buried in the belly of the jar (the exclamation mark shows the separation), and so the getFile does not work.

The solution is to use a different approach:

InputStream in = getClass().getResourceAsStream("/resources/file/test.txt");

The problem is at this point how we access the stream. The solution, for a text file, is to use a Scanner.

But what if we want to use an image? We need to read it from the stream, and we can do it in this way:

InputStream in = getClass().getResourceAsStream("/resources/img/camera-photo.png");
image = ImageIO.read(in);

There is a similar, but slightly different option, by using the Class Loader. In this case, the path we give must be without the leading slash.

InputStream in = getClass().getClassLoader().getResourceAsStream("resources/img/camera-photo.png");

That’s all. So we can give a fully example, which works inside the IDE, from command line and also when launching the jar. The example shows both options (one of them is commented out).


package it.unitn.resourceaccess;
import java.awt.BorderLayout;
import java.awt.Image;
import java.io.IOException;
import java.io.InputStream;
import static java.lang.System.out;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ResourceAccess {
public static void main(String[] args) {
ResourceAccess obj = new ResourceAccess();
}
ResourceAccess() {
printFile("resources/file/test.txt");
showImage("resources/img/camera-photo.png");
}
/** Access a resource file and print its content
*
* @param fileName qualified path, without leading /
*/
private void printFile(String fileName) {
StringBuilder result = new StringBuilder("");
Scanner scanner = null;
InputStream in = null;
//Option 1- with class loader
//in = getClass().getClassLoader().getResourceAsStream(fileName);
//Option 2 - without class loader
in = getClass().getResourceAsStream("/"+fileName);
scanner = new Scanner(in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
out.println(result.toString());
}
/** Access a resource image and show it
*
* @param fileName qualified path, without leading /
*/
private void showImage(final String imageName) {
InputStream in = null;
//Option 1 - with class loader
//in = getClass().getClassLoader().getResourceAsStream(imageName);
//Option 2 - without class loader
in = getClass().getResourceAsStream("/"+imageName);
Image image = null;
try {
image = ImageIO.read(in);
} catch (IOException ex) {
out.println("Caught exception "+ex);
System.exit(1);}
}
JFrame frame = new JFrame();
JLabel label = new JLabel(new ImageIcon(image));
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}

Posted in Java, Programming, Utilities