How to use Docker to build a Skype Bot controlling Jenkins!

Jul 09, 2015

“Besides black art, there is only automation and mechanization.” . Federico García Lorca

Where i work, Jenkins is what we use for continuous integration. Skype is what we use to communicate. Now imagine with me that every day at least 6 times I’m being asked to run a build, another 6 to check the status of the build! another 6 to run a deploy.

And guess what ?! another 6 times to checks the status of the deploy and another 4 questions why the platform is down ?!!

Dolor de Cabeza...

All this because some managers are too scared to let non-technical person touch Jenkins, and some of the non-technical persons are too lazy to take the initiative to know how to run or check Jenkins’s jobs.

I was getting annoyed and bored with this repeatedly tasks when i decided to build a Bot and delegate the task to him!

So every request is sent directly to him as a command, he performs the action automatically and listens for any change on the status of the Jenkins job, if he detects any change or transitions, he sends us a notification.

Dolor de Cabeza...

The Bot is just s python script running on the background as demon, using Skype4Py and Jenkins API module, and some basic logic that can be easily extended.

Communication Diagramm

Things are not so easy as it looks and i will present step by step how i built a functional Bot !

First we cannot run two instances of Skype on the same machine, and i could not use another windows machine, I had access to the server where Jenkins is installed: so why not install Skype there and run the python script?

The Server has no GUI! that was not an issue, I had only to forward X11 socket to my machine, the probleme was that there is no installable version of Skype on that server.

Docker is what i thought of to solve the problem , it was time for free shopping from dockerhub !

I used python:2.7.10 as a base image for my new docker file, and added the instruction to install Skype inspired from jess/skype

FROM python:2.7.10

MAINTAINER Youssef El Jaoujat <eljoujat@gmail.com>

# Tell debconf to run in non-interactive mode
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get -f install --fix-missing
# Setup multiarch because Skype is 32bit only
# Make sure the repository information is up to date
RUN dpkg --add-architecture i386 && \
 apt-get update && apt-get install -y \
 curl \
 --no-install-recommends
# Install Skype
RUN curl http://download.skype.com/linux/skype-debian_4.3.0.37-1_i386.deb -o /usr/src/skype.deb
RUN dpkg -i /usr/src/skype.deb || true

# Automatically detect and install dependencies
RUN apt-get -fy install --fix-missing
RUN rm -rf /var/lib/apt/lists/* # pureg temp data
# Start Skype
ENTRYPOINT ["skype"]

To build this Docker just execute from the command line :

 docker build -t eljoujat/skype .
 

At this point, i have a docker container with Skype and Python installed inside. To test the container , just run the container

docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix  -e DISPLAY=unix$DISPLAY --device /dev/snd  eljoujat/skype

if you get an error with the x11 protocols , just run the following command to grant access to everyone

xhost +

Our Python uses two modules that need to be installed. we have just to add the instruction on the Docker file and rebuild the image.

## Install Python modules
RUN apt-get install -y python-pip && \
    pip install Skype4Py && \
    pip install jenkinsapi

Next step is to make the script available inside the image so we can execute.

A best practice when working with docker is decoupling applications into multiple containers, For the sake of simplicity, I did not completely respect this rule, but it’s simple to apply with the script and make things very easy.

So, to do it I had just to use ‘-v’ option when running the docker image

docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /media/eljaoujat/Linux/job/labs/docker/skype:/scripts/scripts -e DISPLAY=unix$DISPLAY --device /dev/snd  eljoujat/skype:V1.1

/media/eljaoujat/Linux/job/labs/docker/skype is my locale folder and /scripts/scripts will be created inside the container and will be mapped with my locale folder

When running the image, the skype get executed …oups !

i have to accept the term of Use !

accept the term of Use

And login ! accept the term of Use

I have no problem with the term of Use (or I have !?) and login, but doing it each time I run the container is not good at all.

I searched for a solution to automate this on the docker file but with no help, there is no argument we can pass to skype so he will connect automatically.

The only solution I found is to use the commit command of docker.

this command allows you to make the change directly on the running container and create a new image from this changes, it was so easy and simple, i had just to accept the terms, login with the remember me option .

accept the term of Use

and Commit,

docker commit b2ec5c9e295e eljoujat/skype:v.1.1

b2ec5c9e295e is the container ID, can be obtainerd by running:

docker ps

after that I fall in love with docker instantly .

let’s check what happens inside the Container, and test our script . To do this we have to access by ssh, which has to be added to the docker file and rebuild the image.

A better solution is to use nsenter . to install run the following command

docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter

To use nsenter with a running container we should first get his ID

accept the term of Use

Get his PID

PID=$(docker inspect --format  1d46c2cb556c)
 

Then use nsenter

sudo nsenter  --target $PID --mount  --uts --ipc --net --pid
 

After lsing the /scrtips directory inside the container we found our python script.

accept the term of Use

we can also run it and see that’s work well.

At this point all what it’s left to do , is to run the script automatically when the container start.

A good solution I found for this is to use supervisor. supervisor is a process control system and when it’s added to the container it will allow to execute as many processes as we want, we have just to configure them. In our case, we want to execute our pyhton script once the container start, a possible configuration file coud be :

[supervisord]
nodaemon=false

[include]
files = /etc/supervisor/conf.d/*.conf

[program:skype]
command=python /scripts/buildchatbot.py
autostart=true

autorestart=true
startretries=20
stderr_logfile=/opt/nodehook.err.log
stdout_logfile=/opt/nodehook.out.log

So I added supervisor and rebuilt the image with a higher tag version.

The final dockerfile version is :

FROM python:2.7.10


MAINTAINER Youssef El Jaoujat <eljoujat@gmail.com>



# Tell debconf to run in non-interactive mode
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get -f install --fix-missing
# Setup multiarch because Skype is 32bit only
# Make sure the repository information is up to date
RUN dpkg --add-architecture i386 && \
	apt-get update && apt-get install -y \
	curl \
	--no-install-recommends




# Install Skype
RUN curl http://download.skype.com/linux/skype-debian_4.3.0.37-1_i386.deb -o /usr/src/skype.deb
RUN dpkg -i /usr/src/skype.deb || true
RUN apt-get -fy install --fix-missing					# Automatically detect and install dependencies
RUN rm -rf /var/lib/apt/lists/* # pureg temp data


# Install Supervisor
RUN \
  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get -y upgrade

# supervisor installation &&
# create directory for child images to store configuration in
RUN apt-get -y install supervisor && \
  mkdir -p /var/log/supervisor && \
  mkdir -p /etc/supervisor/conf.d

# supervisor base configuration

## Install skype4py and jenkinsapi modules

RUN apt-get install -y python-pip && \
    pip install Skype4Py && \
    pip install jenkinsapi

# add the Supervisor config
ADD supervisor.conf /etc/supervisor.conf


CMD [ "sh", "-c", " supervisord -c /etc/supervisor.conf && skype" ]
  • To build :
docker build -t eljoujat/skype:V1.2 .
  • To run :
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /media/eljaoujat/Linux/job/labs/docker/skype:/scripts/scripts -e DISPLAY=unix$DISPLAY --device /dev/snd  eljoujat/skype:V1.2
  • To test : just send a messgae to the jenkins Bot telling him to run a job .

“I believe that there is always an other way to do it, and i hope that you let me know .”