We previously looked at making a basic Docker container which allowed interaction from a user. The container could be used on another system by being moved to another Linux Operating System or even a Windows or MacOS system running Docker. In this article we will be going over making a more advanced container. The container will not be interactive like the previous one. The container we will make will be accessible from other systems on the network. To do this we will be doing a lot different things to accomplish making the container so there will be a lot to learn. Setting Up a New Container The container will be running a Minetest server which is a clone of Minecraft. The Minetest server can be accessed from Minetest clients to allow for multiple players to access the same world. NOTE: Be aware that the world created is lost once the container is stopped. This is mainly for the purpose of demonstrating the method to create a container. There are methods to retain the data in the container which we will cover. In your folder ‘~/Docker/’ create a folder named ‘MTServer’. Within the ‘MTServer’ folder create the file ‘dockerfile’ and place the following in it: Code: FROM ubuntu:xenial RUN apt update RUN apt install software-properties-common -y RUN add-apt-repository ppa:minetestdevs/stable RUN apt update RUN apt install minetest -y RUN mkdir /root/.minetest COPY ./minetest.conf /root/.minetest/minetest.conf CMD ["/usr/bin/minetest","--server"] The first line ‘FROM ubuntu:xenial’ is different than we used in the previous article. We are not getting the most recent version of Ubuntu, but getting Ubuntu 16.04. To see other options you can go to hub.docker.com. In the Search bar type in ‘Ubuntu’. A list of results should be displayed and you need to find and click on the result for ‘Ubuntu’. If you scroll down you should see a list of ‘Supported tags’. You can see the one line shows the version 16.04 and has three different names. You can use any one of these names to specify the version of the base image to use. Any version of Ubuntu should be acceptable, but I am specifically using Xenial to show how to get a different base image version. The second line of dockefile is ‘RUN apt update’. When you need to perform a file installation to your Linux distro you need to first download a fresh copy of the repository information. The third line, ‘RUN apt install software-properties-common -y’, adds the software which is needed when adding a repository which is done on the fourth line. Try to make the lines run without any interaction by using the parameter ‘-y’ when possible. The fourth line adds the repository for Minetest and the fifth line updates the repository information since a new repository was added. The line ‘RUN apt install minetest -y’ causes the minetest program to be downloaded and installed from the new repository. The seventh line, ‘ RUN mkdir /root/.minetest’, causes a hidden folder within the Root folder which will be used by Minetest. Once the folder is created in the script we will need to copy a configuration file to the new folder in line eight. The file is copied from the Host’s folder at ‘./minetest.conf’ to the container folder ‘/root/.minetest/minetest.conf’. The configuration file will be downloaded and prepared shortly. The last line specifies the command to run when the container is started. The command is located in ‘/usr/bin’ and is called ‘minetest’. We are passing a parameter to it which is ‘--server’ that forces the program to run in server mode. Any parameters passed to the Docker container must be each contained in double quotes and separated by commas. Now that you can see what is occurring in the script to set up the container we can continue with getting everything ready to create the container. The ‘minetest.conf’ file is ready to be downloaded and configured for use by the minetest server. Change to the folder ‘MTServer’ folder with the command: Code: cd ~/Docker/MTServer Once you are in the appropriate folder you can download a copy of the ‘minetewst.conf’ file with the command: Code: wget https://raw.githubusercontent.com/minetest/minetest/master/minetest.conf.example The file should download and you can edit the file to make changes if you want, but none are needed. The file needs to be renamed so it will be copied by the script into the container with the command: Code: mv minetest.conf.example minetest.conf The file should be ready to be copied into the container by the ‘dockerfile’ script. To create the container you need a Docker ID which you can create at https://hub.docker.com/signup for free. The username you choose is your Docker ID. The Docker ID is needed if you plan on sharing your image on the Docker Hub. Use the following command from the ‘MTServer’folder to create the Docker image, but replace ‘<ID>’ with your own Docker ID: Code: docker build -t <ID>/mtserver . You should see the image being built and hopefully a successful build. If any errors occur make sure the dockerfile is the same as I have posted above and all files are in the proper folder. If you want to practice all of the steps for a new image you can easily just create a container with only the Base image (ubuntu:xenial) and start it with the ‘-it’ parameter. Within the started container you can perform each line to verify it works as intended. Keep notes of every line you perform and make sure all of them are included in the ‘dockerfile’ when building the image. NOTE: To start a container for testing the commands you want to use in the dockerfile use: ‘docker run -it ubuntu:xenial sh’. To start the Minetest server we need to run the newly created image in a container. The following command can be used: Code: docker run -p 30000:30000/udp <ID>/mtserver Again, you need to use the Docker ID you used when building the image. The ‘-p’ parameter is needed to pass data through the Host Port of 30000 to the Minetest Container port of 30000. The first 30000 is for the Local Host Machine and the second is for the Container Port. We are specifying the use of UDP which is needed for Minetest. If UDP was not signified then it would default to TCP which is not used by Minetest and the connections from a client would not work. The Port numbers do not need to match, but in this case I did not want to over-ride the default of 30000 on either the server or client software. Docker Networking Let’s look just a little at the Docker Networking system. On the Host System you can run the command ‘ifconfig’ in a Terminal. You may need to scroll up, but you will see an entry for a Virtual Bridge called ‘Docker0’. The bridge created can be changed, but I would not advise it until you have a better understanding of the Docker networking subsystem. The Docker0 Bridge is used to pass network communications through to the container which is on its own virtual network. If a specific port is needed then you must use the ‘-p’ parameter to specify the port numbers to use to bridge between the Host and the container. NOTE: If you remove or change the Docker0 virtual bridge then your container most likely will not be accessible from client systems until the bridge is fixed. Just think of the bridge as being a pathway between the physical network to the virtual network to allow communications with the container. It really does ‘bridge’ the two networks. Client Software Connection On another system you can start Minetest. Select the tab for ‘Play On-line’. Enter the IP Address of the Host system in the Address box and make sure the Port number is ‘30000’. Enter a name you want to use with a password. The password will not be asked a second time for verification and it is required each time you connect to the server. If you should forget or mistype the password you can just use another Name and Password. The Minetest Server container can be stopped and restarted at any time causing all of the data to be lost and you can start over. Any worlds created will also be lost if the container is stopped completely or the system is restarted. How then can information within the container be saved? Saving Container Data With some containers there may be data which will need to be saved to be part of the container if it is stopped and restarted. In this example who would want to spend time creating a world only to have it lost every time the Docker Host System had to be restarted? Let’s look at saving the container and its current data. For our Minetest container we should probably stop all clients from accessing the container and continuing to change the world. Once all clients have been disconnected you need to keep the Docker Minetest Server container running and open another Terminal window. From this new Terminal we can issue Docker commands which can affect the running container. You need to issue the command: Code: docker ps -n1 The command will list the containers, but I am using the parameter ‘-n1’ which lists only the last opened container. The number after the ‘-n’ specifies how many containers to list. The results of my command is shown in Figure 1. FIGURE 1 You can see that the image is ‘jarretbuse/mtserver’. The container also has a Container ID which can be used to designate the container. The command which is executed by default when the container is started is also listed. Other information about the container is also shown, but the one to look at is the ‘Names’. The MTServer container is also in this instance named ‘vibrant_swirles’. Everytime the container is started the name will change to have a unique Instance Name. NOTE: The ‘Container ID’ can be used in place of the ‘Names’ option in most cases. To save the current data within the container we need to commit the changes to a new container. You can use the same container name or a new one. In this example I will use the same one. To commit the changes I use the following command: Code: docker commit vibrant_swirles jarretbuse/mtserver The command uses the current instance of the running container named ‘vibrant_swirles’ to be saved. The container and all of its current data will be saved as the image ‘jarretbuse/mtserver’. The current container and its data is running so everything is fine. If you should change the name of the image then you need to stop the current container and start the container using the new image name you created. Stopping a Container To stop a running container you need to use the command: Code: docker stop <dockerID>/<image-name> In the previous case the command would be: Code: docker stop jarretbuse/mtserver Once the container is stopped then there can be no interaction with the container until it is restarted with the ‘docker run’ command. Conclusion (Log in to hide this advertisement) There is a lot of information being used in this article for the images and containers themselves. Be sure to practice this example and connect to the Minetest server from a client. The client can be on a different system on the network or even the Docker Host System. Try different things and see what you can accomplish.