Simplifying Development Workflows: Dockerized Ubuntu and Ansible in Action

Muthukumaran Navaneethakrishnan
3 min readMar 19, 2024

--

Introduction:

I’m working on a tool designed for deploying applications on self-hosted Kubernetes clusters and setting up domains in Nginx. This tool mainly uses Ansible for tasks like managing domains and installing software on remote systems

Development Challenges:

My development is always driven by tests , but it’s often slowed down because Ansible needs to connect to real systems, which in my case are hosted on Contabo. This can be slow and cumbersome. Plus, resetting these systems to test different scenarios is a complex and time-consuming task

Addressing Slow Testing and Infrastructure Reset with Docker

To tackle these issues, I’ve been weighing up using either virtual machines or Docker. While VMs have their uses, they’re slower to reset, which is a major consideration in my case. So, I’ve decided to go with Docker. In this article, I’ll explain how I set up two Ubuntu Docker containers with SSH access, and how I use these with Ansible to make my testing process quicker and more efficient

If you would like to just get the source code rather than reading any , Click here

Creating a Custom Docker Container:

Here’s how I set up a Docker container for testing:

Custom SSH Setup:

I wrote a shell script as an entry point for the Docker container to create a user with root access and no password requirement for sudo. The script also starts the SSH service. Here’s the script:

  #!/bin/bash
# Script to create a user and start SSH service
useradd -rm -d /home/$DOCKER_SSH_USER -s /bin/bash -g root -G sudo $DOCKER_SSH_USER
echo "$DOCKER_SSH_USER:$DOCKER_SSH_PASSWORD" | chpasswd
echo "$DOCKER_SSH_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$DOCKER_SSH_USER
/usr/sbin/sshd -D

Dockerfile Configuration:

I created a Dockerfile to set up this environment, installing necessary packages and adding the entrypoint script. Here’s the Dockerfile:

   FROM ubuntu
RUN apt-get update && apt-get install -y openssh-server sudo
ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/entrypoint.sh"]

Building and Running the Docker Container:

After writing the Dockerfile, I built the Docker image and used Docker Compose to set up two servers with different SSH credentials and ports.

Building the image

Run the below command on the same folder as Dockerfile

   docker build -t ubuntu-ssh .

Docker Compose Setup:

I wrote a docker-compose.yml file to create two instances of the ubuntu-ssh container, each with different user credentials and ports.

version: '3.8'

services:
ubuntu1:
image: ubuntu-ssh
environment:
DOCKER_SSH_USER: user1
DOCKER_SSH_PASSWORD: password1
volumes:
- ./server1:/home/user1
ports:
- "5222:22"

ubuntu2:
image: ubuntu-ssh
environment:
DOCKER_SSH_USER: user2
DOCKER_SSH_PASSWORD: password2
volumes:
- ./server2:/home/user2
ports:
- "5223:22"

Starting the Containers:

start the containers by running the below command

docker-compose up

Accessing the Servers:

To access these servers, I use SSH with specific commands to bypass certain security checks, as these are local test servers:

Logging into Server 1:

ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no user1@localhost -p 5222

Logging into Server 2:

ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no user2@localhost -p 5223

Integrating with Ansible:

To automate tasks on these servers,

  • Install SSHPass
# Mac
brew install hudochenkov/sshpass/sshpass


# Ubuntu or WSL2
sudo apt-get install sshpass

  • Update Inventory files
[servers]
localserver1 ansible_ssh_host=localhost ansible_ssh_port=5222 ansible_ssh_user=user1 ansible_ssh_pass=password1 ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
localserver2 ansible_ssh_host=localhost ansible_ssh_port=5223 ansible_ssh_user=user2 ansible_ssh_pass=password2 ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
  • Test Ansible can access the servers
ansible  localserver1 -m ping

Conclusion:

This setup has helped for my faster development , It’s faster and more cost-effective than connecting to remote machines or using virtual machines . All the source code for this project is available on GitHub.

--

--

Muthukumaran Navaneethakrishnan
Muthukumaran Navaneethakrishnan

Written by Muthukumaran Navaneethakrishnan

Software Engineer works on Java, Javascript & Clojure

No responses yet