- Docker Engine for Linux Containers
- TeamCity as CI Server
Dockerfilecreates container image with all the infrastructure required for Mobmerry- Ruby
- MongoDB
- Elasticsearch
- Redis
- Nodejs
docker_scriptsfolder contains scripts required to configure and start the container:test_entrypoint.shruns when container starts, it starts all services and does some prerequesite work to run tests.wait_for_it.sh(from this github repo) waits for all services to be up and listening.
Build the image using:
docker build -t interactionone/mobmerry:v1 .
Here interactionone/mobmerry is the name for image, you can give any name.
And v1 is the tag / version.
-t flag will attach a pseudo tty to the image building process to see the output
The above command will use any cached image layers if available in the system.
If you want to start afresh and not use any cached image layers, use:
docker build -t --no-cache interactionone/mobmerry:v1 .
There are two modes you can run the container as facilitated by test_entrypoint.sh
In this mode, when you start a container with a command, the container executes that command and exits.
For Eg:
docker run -it --rm interactionone/mobmerry:v1 rspec spec/models
Here rspec spec/models is a command that runs against a new container that is started.
When the command exits, the container stops and exits.
-itwill make container interactive (i) and attach a tty (t) to the container process running-rmwill remove the stopped container as soon as process exits
To gain shell access to the container:
docker run -it --rm interactionone/mobmerry:v1 /bin/bash
This executes /bin/bash command against a new container that is started.
You can start a container to run in a standby mode - as in no command is provided to execute immediately but gets container ready to accept any commands passed to it subsequently.
docker run -d --name mobmerry_app interactionone/mobmerry:v1
This will have the container named mobmerry_app started and waiting for executing any commands to be passed to it as such:
docker exec -it mobmerry_app rspec spec/models
The container will receive the command, execute it, go back to the standby mode.
-dwill start the container in daemon mode
To get shell access to such idle container
docker exec -it mobmerry_app /bin/bash
To stop such a container
docker stop mobmerry_app
You can start many containers, either in standby or command mode - the number is only limited by system capabilities
Install and start TeamCity by following instructions here
TO USE POSTGRES DB, read this guide from TC
By default TeamCity comes with a single Build Agent
Number of Build Agents determine how many parallel executions you can do in a build.
So we will install 2 additional build agents in the same machine - max allowed for free TeamCity license.
- Go to
AgentsTab in TeamCity web UI at http://localhost:8111 - On
Install Build Agentsmenu on top right selectzip file distribution - Unpack the zip to a folder - and make 2 copies of the same folder - for 2 build agents
- In
conffolder of each of the agents, renamebuildAgent.dist.propertiestobuildAgent.properties - In
buildAgent.propertiesprovide a differentname=of each of the build agents - Do
bin/agent.sh startin both the agent folders to start the agents. - This can be added to an init script, alongside the start procedure for TeamCity.
Create a new CI user
Create a new project Mobmerry
In Project Settings add a VCS Root, use auto-detect from URL option, use github URL in Repository URL with username and password.
--> Create.
Edit the created VCS Root as some configuration options does not show up when creating it.
Click on Show advanced options at the bottom of the page, locate Branch Specification config field and add this
+:refs/heads/*
+:refs/pull/(*/merge)
- The first specification will pick up all branches in the github repo to run CI Build on
- The second specification picks up pull requests from github to run CI build on
Current setup we have 4 build configurations - better to call them as build steps
-
CI Setup
This step will:
- copy mobmerry config files to checked-out commit folder
- build the mobmerry image using image layer caching and picking up only changed contents from checked-out commit - thus being very quick
-
CI Test Channel 1, 2 and 3
- These steps will wait for
CI Setupto end, then all of them start parallely in 3 agents configured. - They each start up a container built from
CI Setupand pass a command to execute for eg:rspec spec/models
- These steps will wait for
Now we will create these Build Configurations.
Go to Mobmerry's Project Settings locate Build Configurations and click Create build configuration
Create 3 configurations with the names as mentioned in steps above.
Edit each of the Build Configurations from Project Mobmerry's settings page
-
CI Setup
Version Control Settings - Attach existing VCS root --> Select Mobmerry VCS Root
Build Step - Add Build Step - Runner Type: Command Line -
-
Build Script -
cp ~/mobmerry_config/* ./config/ docker build -t interactionone/mobmerry:v1 .
Triggers -
New Trigger -
VCS Trigger- Check
Trigger a build on each check-in - Add a new Trigger --> Select
Trigger Build, let other configs here be default values. - Click on
Show advanced options--> inBranch filter, add rule-:*/merge, this will not trigger builds for any new pull requests that may come. Great video here to learn on how to set up VCS branch specifications everywhere
Parameters -
- Add
env.DOCKER_HOST=tcp://localhost:4243
-
-
Test Channel 1, 2 and 3
Build Step - Add Build Step - Runner Type: Command Line -
-
Build Script -
Add different rspec folders to test in each of the Channels
As:
docker run --rm interactionone/mobmerry:v1 bundle exec rspec spec/models
Triggers -
- Wait for CI Setup to finish in all of the channels to parallely trigger off all channels
Parameters -
- Add
env.DOCKER_HOST=tcp://localhost:4243
-
You can also manually run builds by going to build configurations and clicking run button. But this will not trigger the dependent child builds.
-
In teamcity's build agents you cannot access docker for some reason even though agent runs on same user
So this needs to be done :
in /etc/default/docker file add DOCKER_OPTS="-H tcp://localhost:4243 -H unix:///var/run/docker.sock" save and close file restart docker service Add environment variable DOCKER_HOST=tcp://localhost:4243