Last time I walked through my experience of Docker on Windows. Now it is time to see if any of that knowledge is transferable to Docker on Linux.
But before that I wanted to call out a seemingly an obvious statement for people equating containers to virtual machines. With Virtual Machines you can run a Linux guest on a Windows Host and vice versa because the hypervisor is pretending to be bare computer with no OS running on it. This is not the case with containers as the host operating system is available to the software running in the container. Therefore you can only run Windows containers on a Windows machine and you can only run Linux containers on Linux machine. Containers can do a lot of things but they are not magic. And as ninety nine percent of the available containers are Linux ones… you still be doing a lot of work with Bash!
In order to translate the experiences I have had understanding Docker on Windows to Linux I thought I would try setting up something I was ready familiar with. So I went about trying to set up TeamCity. The one thing I decided to do to help my understanding was to set up the main TeamCity server and one build agent in separate containers. Whilst in this write up they are sharing the same host machine, having the two components in separate containers should allow you to scale up with ease.
So where to start? Obviously you could go the whole hog and install a flavour of Linux into a VM, but I went for a simpler solution. I decided to use one of the Amazon Web Services pre baked Linux EC2 instances. You can do this for free if you select the right instance size. So sign up for an AWS account and create a new Amazon Linux T2-Micro EC2 instance. The T2-Micro size is part of the free tier so you won’t be charged.
It is relatively straightforward to set up Docker on an Amazon Linux instance. Use this guide to get you started.
We are going to setup TeamCity but where to start. If you were doing this outside of the container world you would obtain the installation package , install in on the target machine and then configure it. However you won’t be surprise to learn with container it is easier.
Docker maintains a hub of all public repositories at hub.docker.com. Whilst it is possible to search and browse it, you do really need to known what you are looking for. So for this post we’ll be using
The next step is to get these container images onto your machine. In the terminal window, issue the following two commands
docker pull jetbrains/teamcity-server docker pull jetbrains/teamcity-agent
You may notice one of the benefit of containers at this point. Whilst the first command downloaded a number of container layers, the second gets away with only downloading a smaller subset – the
teamcity-agent container shares many of its base layers with the
Last time when I started containers I had to map the ports exposed by the container to ports exposed by the host machine. With these TeamCity container images you have to do that and more. Not only is there a requirement to expose ports but you also need to map file locations too.
TeamCity adapts its behaviour based on a number of configuration settings. You tweak them as you see fit. These need to be located on the host and mapped to the container because if they weren’t you’ll lose all of your changes each time the container started. The same goes for the logs output from TeamCity . If you don’t map the container’s log path to somewhere on the host then you’ll lose them if the container is stopped. We’ll need to do the same for the agent container.
Therefore create the directory structure on the host that we will map to the containers
sudo mkdir -p /data/teamcity_server/datadir sudo mkdir -p /opt/teamcity/logs sudo mkdir -p /data/teamcity_agent/conf
Then we can start the teamcity-server container with the following command. We expose ports through the
-p argument and we map volumes through the
-v arguments. It is useful to start in interactive mode the first time. That way you’ll see the teamcity start up process and can look for any problems.
docker run -it --name teamcity-server-instance -v /data/teamcity_server/datadir:/data/teamcity_server/datadir -v /opt/teamcity/logs:/opt/teamcity/logs -p 8111:8111 jetbrains/teamcity-server
As it starts up it wants to ask you a number of questions through the web site. Open a browser and navigate to port 8111 on the hosts IP address. You did remember to set up your security group in AWS EC2 correctly didn’t you? If you did you’ll see the screen below. If not, ensure you have a security group rule for port 8111.
The initial process is building up the configuration files that are stored on the host at
/data/teamcity_server/datadir. Once TeamCity has finished setting itself up exit the container via [CTRL]+C+ because it running interactively. You’ll find various directories and files if you look at this location. They will be used to configure the teamcity-server container the next time it runs.
Starting the container again is a bit easier. Run
docker ps -a to find the container id, then run
docker start [containerId]. You can switch back to the web site to see it loading. A T2-Micro is not the most powerful machine so the start-up process may take some time.
Now it is time to start the agent. The process is very similar. This command starts the agent in detached mode.
docker run -d -e SERVER_URL="http://[host_ip]:8111/" -v /data/teamcity_agent/conf:/data/teamcity_agent/conf jetbrains/teamcity-agent
The thing to note here is the
-e SERVER_URL="http://[host_ip]:8111/". This allows you pass in custom settings into the container. In this case you are passing the public URL of the TeamCity server in so the agent know where to connect.
You can check whether this has worked by looking in TeamCity server website
You should see an unauthorized agent. This can be authorised to be a normal team city build agent. This team city running in containers.