Outfitting an IT training environment with Docker containers
Trainer Container
Containers offer better performance than virtual machines because containers consume fewer resources and don't require a hypervisor. Containers also isolate a work environment from the rest of the system, so a user working within the container can't bring down the server or damage other user spaces. We put Docker containers to work on a problem we had on our network: creating workspaces for users in IT training support classes. Using Docker and some basic shell scripting, we built an automated environment where we could create temporary containers for each user in a lab class and delete those containers at the end of the session.
A Script for Creating Containers
Docker Hub [1] is a repository for Docker images. You'll need a standard Linux Docker image for creating containers. Docker Hub offers images for different Linux flavors, including Ubuntu, RHEL, Fedora, and CentOS.
This article assumes you have Docker up and running on your Linux system. If you don't have Docker on your system currently, you'll need to install the necessary and dependent packages – see the documentation for your own Linux distribution.
The next step is to download the base Docker image from the registry by executing the command
$docker pull <image>
where <image>
is name of the any official Linux flavor from the Docker registry [2].The downloaded image has minimal utilities for executing shell scripts or basic Unix commands.
You can configure the Docker image to add more functionality. For example, in a development environment, one needs a good editor, manual pages, and compilers for different programming languages, debuggers, and system monitoring tools.
The next step is to create and run the container for a user.
As the sys admin, you create a user account and share the credentials for the user to access the Linux server. The objective is to provide the user with an isolated container with root privileges. However, you need to be sure the user doesn't use the root privileges outside of the container environment.
We overcame this security challenge by providing access to the user to execute Docker commands, but preventing the user from operating outside of the container. As you will learn later in this article, we use the .bash_profile
and .bash_logout
files to keep the user from accessing other parts of the system. (See the box titled ".bash_profile
and .bash_logout
.")
Creating User Containers
In our lab, we needed to create two Docker images from the standard Ubuntu base image: a dev_test
image (for a development environment) and sysadmin_test
(for performing system administration tasks).
In the DevOps era, we need to train software professionals in all three essential areas: development, testing, and deployment. For our training sessions, the dev_test
image is used for development as well as testing and the sysadmin_test
image is used for deploying applications.
System administration tasks typically require root privileges, so system administration training requires some kind of root access. The challenge is to give students root access without allowing them to break the server. Containers make it very easy to assign each user a separate work environment. A single Docker server hosts several containers to support several users. Users can only access their own container.
To create a container from the selected image, execute the command:
$docker create -i -t --name <container name> <docker image> /bin/bash
The -i
option keeps standard input open, the -t
option allocates a pseudo-terminal for the container, and the --name
option assigns a unique name for the container.
For example, say a student with username Rama wants to develop a program using the dev_test
image. The following command creates a container named Rama
:
$docker create -i -t --name Rama dev_test /bin/bash
After creating the container, Rama (the user) needs to start the container and run it to get the container access by executing the command:
$docker start -a -i Rama
The -a
option is to attach standard output and standard error. The -i
option attaches the container's standard input.
To stop the running container, Rama needs to execute the following command:
$docker stop Rama
The system administrator needs to automate the startup and run the container whenever Rama logs in to the server. When the user logs in, the .bash_profile
file is executed before the user gets to see the system's shell prompt. To put the user in the container, you need to append the following command to Rama's .bash_profile
file:
echo sudo docker start -a -i Rama >> /home/Rama/.bash_profile
The preceding command will put Rama inside the container at login.
However, when exiting the container, Rama ends up at the server command prompt, which is a security breach for our network. Therefore, you need a way to make sure Rama exits the server completely when exiting the container. To achieve this, add the following command in .bash_profile
:
echo exit >> /home/Rama/.bash_profile
As soon as Rama logs out from the container, the above code is executed. Rama will exit from the SSH session and thus will not get a chance to access the server.
The .bash_profile
file modification is to be done immediately after creating the Rama user account or before sharing the login credentials with the user.
Automate with a Shell Script
To automate container creation for a user, a sys admin can use the script shown in Figure 1, which will execute in an interactive way. Script execution will prompt the user to enter a username and the docker image. Afterward, the script will create a container with the username and modify the user's .bash_profile
file accordingly.
A Real-Life Case Study
We have been in the IT education and development field for more than a decade. The main objective of conducting technical training is to equip employees with bleeding edge technologies that meet current and future demands of businesses. Employees gain practical knowledge of the necessary skills before entering into real project or product development. The classes help employees become multiskilled professionals.
The training sessions train users on various streams of IT, such as system administration, product and application development, programming languages, and DevOps.
We typically train a large number of employees every month, so creating the necessary development environment and providing the necessary privileges for each user are major concerns because of the variety of technologies.
Also, it is always a challenge to monitor hands-on activities for online training participants. An instructor must monitor multiple participants simultaneously and debug a program in order to help participants work in different locations.
Our solution is to use the RHEL 7 platform to create a Docker system. An Ubuntu Docker image is used as a base image. From the base image, we have created custom Docker images catering to our training requirements, as shown in Figure 2.
Each image includes the necessary tools and documents, such as an editor, man pages, compilers, debuggers, performance monitoring tools, a list of lab exercises, and tasks for hands-on assessments. Instead of keeping all these items in a single image, we built each one targeted for a specific purpose, so that only the necessary packages are installed to keep the size optimal.
A shell script lets a system administrator automatically set up a batch of users. The automation script creates user accounts, sets passwords for each user, creates a container for every user, and modifies the .bash_profile
for the new users, as shown in Figure 3. The sudo
utility is not required for the user to start a Docker container.
The script in Figure 3 offers the option of choosing the number of containers you want to create. You can choose the Docker image from a list based on your specific training requirement. At the bottom of Figure 3, the command
useradd user$i
creates a user account. The i
value represents the user number.
echo "user$i@123" | passwd --stdin user$i
sets the user password.
If the value of i
is 1
, the username will be created as user1 and the password will be set to user1@123.
For a host system, we used a desktop computer with 8GB of RAM, an Intel Core i7 processor, and a 500GB hard disk to cater to infrastructure needs for technical trainings. In our experiment, we created 25 containers, and it took just 39 seconds, including creating 25 user accounts, setting passwords, and modifying user profile files.
To list all the user containers, you just need to execute the command:
$docker ps -a | grep user
The output of this command is shown in Figure 4. (The output just shows 10 of the 25 containers created.) Note that the container name is the same as the username to identify a running container with its user.
To monitor the resource usage for all running containers, execute the command:
$docker stats $(docker ps -a | grep user | awk '{print $NF}')
The docker stats
command with container ID or name will print the computing resource utilization. To monitor container details for all users, list all the running containers (docker ps -a
). You can then filter with only a user container name (grep user
). To extract the container name of all users, cut the line with only the last field (awk '{print $NF}'
), which is the container name. Pass this containers' names list to the docker stats
command.
The resource utilization of 10 user containers is as shown in Figure 5. The displayed output is refreshed periodically. If you want to exit from the screen, press Ctrl+C.
To monitor the specific running container activities online (STDIN
, STDOUT
, and STDERR
) as a system administrator, you can attach the container in your terminal by executing the command:
$docker attach <container name>
The command will attach your terminal with the running container, and you can view activities going on in the container. You can also take control of the container if you want to show a demo to the user. When you exit from the attached container, the running container also exits. Therefore, the user needs to log in again to get container access. To avoid this complication, first press Ctrl+P and then Ctrl+Q, which will detach your terminal without affecting the user's container.
To check the logfiles of the container in a server, whether it is running or stopped, you can get the log info by executing the command:
$docker logs <container name>
If you want to check in online without attaching the container, execute:
$docker logs -f <container name>
The -f
option will continue streaming the new output from the container, although you cannot get control of the container when you use -f
to attach the running container. To exit from the log screen, press Ctrl+C.
If you want to delete a specific container, use the command:
$docker rm <container name or ID>
If you want to delete all the existing containers, use the command:
$docker rm $(docker ps -a -q)
To clean up the system after the training session, use the script in Figure 6 to delete all user accounts, their home directories, and the related containers.
In Figure 6,
userdel user$i
deletes a user account, where i
is the user number;
rm -rf /home/user$i
removes the user-related files and directories; and
var1=`docker ps -a | grep user$i | awk '{print $1}'`
lists all the existing containers (docker ps -a
), filters the list for the user with user number i
(grep user$i
), and truncates the list to the first field only (awk '{print $1}'
) – the container ID – which is stored in the var1
variable. The final line,
docker rm $var1
removes the container with the given ID number.
Conclusion
Providing lab infrastructure for hands-on exercises is a major challenge for technical training sites. Docker images let you easily create the containers you need to support a training class, and you can even give each user a personal container with root access.
Each running container provides an isolated environment from the host with independent root access for each participant. Monitoring users' systems in real time is possible through logfiles by using simple commands.
The creation of user accounts and allocation of containers for each user is automated through a shell script. After completion of the training sessions, you can delete the containers and user accounts with a shell script, as well. With some basic scripting and a little knowledge of Linux container technology, you can easily overcome the infrastructure challenge for supporting hands-on training.