What are we doing here?

This blog includes a series of videos and references to help new users or enthusiasts better understand how to use open source and free technology tools. The quick links includes more information for accessing many of the tools covered along with other references to learn more for taking advantage of these tools.

Click HERE to see the full list of topics covered!

Connecting new Docker Containers to an Existing Docker Compose

Docker is amazing, but it has it's own way of handling things. 

Docker-Compose is amazing and it to needs to be used the right way. 

This post is about explaining how to attach new containers to existing containers already set up via docker-compose. 

Background:

Docker-Compose, when it brings up a bunch of containers or 'services' puts all of them in the same network with a common subnet and DNS so each service can talk to one-another based on the service name. 

Example:

mongodb://root:mongopwd@mongo:27017/

The 'mongo' in that line is the service name, and to connect say Mongo-Express to that container we can simply call the service name. Without the DNS component of the networking layer, we would need to know the specific IP of the container to connect. The 27017 is the port which is the default for MongoDB. 

Normally with Docker-Compose all the services or containers that run within the config file - normally docker-comopose.yml - will be given their own subnet and DNS to operate so they can just talk to one-another based on the service name. 

Example:

version: '3.1'

services:

  mongo:
    image: mongo
    container_name: mongodb
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: mongopwd

  websvr:
    build: ./work
    container_name: web4mongo
    restart: unless-stopped
    volumes:
      - ./work/src:/var/www/html
    ports:
      - 80:80
    links:
      - mongo
    depends_on:
      - mongo

The services are denoted using indentation, and shown as 'mongo' and 'websvr'. Those two can than talk to one-another using 'mongo' or 'websvr' rather than the IP address of each individual container. This is really powerful since it makes the networking portion more easily understood, and also more easily repeatable since containers brought up on one system may get assigned different IP ranges than say on a different system. From a code perspective, just call the service name each time and all of that is handled. 

Adding another container:

However say we want to add a container. Often you need to adjust the docker-compose config, stop / remove the containers, and restart them. If the containers are removed and don't have a mapped volume to store the data already created, than the data could be lost. 

Less than ideal. 

However, with Docker you can map new containers to the network!

First find the network. Run 'docker network list'

 NETWORK ID     NAME                                DRIVER    SCOPE
50711*******   bridge                                bridge    local
ca9cc
*******   host                                  host      local
118ef
*******   lamp_default                          bridge    local
1887b
*******   local-debug_default                   bridge    local
9299d
*******   none                                  null      local
06023
*******   ournoteorganizer_default              bridge    local
186fc
*******   phps3object_default                   bridge    local
2209e
*******   wordpress_default                     bridge    local

An output like the above may be what you see depending on the number of Docker instances you are running or have setup. This gives us the network names which we can use to attach a new container in the network. 

For this example we are adding a Mongo Express which is a web-based graphical UI that helps see and interact with a MongoDB database more easily. It's not necessary and should be disabled (docker stop mongo-express) when not used, but it is clearer, and possibly faster than running through all the mongosh commands.

Here is what we run:

sudo docker run --name=mongoex -p=8082:8081 \
--network=ournoteorganizer_default \
-e ME_CONFIG_MONGODB_ADMINUSERNAME=root \
-e ME_CONFIG_MONGODB_ADMINPASSWORD=mongopwd \
-e ME_CONFIG_MONGODB_URL=mongodb://root:mongopwd@mongo:27017/\
mongo-express

We create the new container using the run command, give it a name, define the port mapping between the host and the container, then assign it to the same network as the the original Docker-Compose group of containers - placing it in the same subnet and DNS / user space. Then we assign the necessary environment varilables to match the existing ones shown in the previous docker-compose.yml file. Finally specific the Docker image as mongo-express. 

This worked a treat for me since I had commented out Mongo Express in my pusblished OurNoteOrganizer application due to security concerns. Now I have a Mongo Express container I can call up when I need it or turn it off when I don't. 

Start: sudo docker start mongoex

Stop: sudo docker stop mongoex

Docker Compose is amazingly powerful, but understanding how it works is important to take full advantage of it. Knowing that it is essentially an automated networking stack + container creation makes it possible to work with without having to destroy containers and possibly lose information.

Ada & Zangemann


Ada & Zangemann is a book by Matthias Kirschner and Sandra Brandstatter that extols the benefits, fun, and importance of software freedom. A fun read for kids, it strives to instill a passion for inventing and tech into kids, and also has an important lesson for adults not to rely on any one person or organization for all their software needs. 

The premise of the story is around the juxtaposition of Ada - a bright girl without the means to afford many of the fancy tech most other families have - and Zangemann - the inventor of said tech. Through necessity, Ada tinkers with broken gadgets and old bicycles to give them a new life and make up for her lack of fancy skateboards and ice cream machines that other children have. In her drive to build the solutions she wants and needs, Ada finds her passion for problem solving, and hardware and software development. 

Zangemann, who is designed with an obvious reference to other high-tech oligarchs, is trapped by his own idiosyncrasies. He tends to go overboard in locking down devices to do only the things he wants to do - like his ice cream flavor of the day rather than letting people choose which flavor they want. He designs the products he likes, but wants them to be used in ways that only he deems appropriate. Obviously, the book is a bit over-the-top in some of the things Zangemann imposes on people, such as the iron that can't iron ties because Zangemann hates ties. That said many of the examples are probably more benign than the data and privacy society has given up to much of the tech giants of the world.

As the story progresses, Ada with her friends become more and more interested in tinkering with inventions and modding the many inventions that Zangemann sells. Zangemann becomes angry about the mods, and tries to get the government to step in and create laws to stop it. Ada and her friends, with the help of family protest, and over time end up not merely overturning the law, but also helping the government by creating new software without the limitations of the Zangemann tech. The government in the story saw the power Zangemann had over them with his digital monopoly, and our hero, Ada, was able to help out with her skills.

The story is a fun, inspiring adventure that I can relate to quite well. I want to be Ada! The political side is important as well, and speaks to the work Matthias Kirschner does as his day job as the President of the Free Software Foundation Europe (FSFE). This blog is really just designed to be a free resource to help people get off the ground and start learning about software, and honestly very little to none of the knowledge that I've learned would have been possible without free and open source software.

Ada & Zangemann is an approachable read that children and politicians alike can understand and hopefully take away some insight into the value of software freedom. Similar to this blog detailing my own experience learning about free tools and writing code, catching that feeling of "wow I built this" is incredibly important for young children. Free and open source code help enable the education, either in the classroom or self-taught, for those just getting started with technical development.

Free tools are resources that are essential for enabling more people to learn and develop new skills. It's very hard for many, myself included, to justify spending money on tools and software when I may not end up using it, or decide it's too difficult to learn, or I lose interest in something. However, if the tools are free, then one can use them and start to learn and develop one's skills further. If the tools are open source, then there is an even greater benefit because the code is more likely to have been peer reviewed, and more people can contribute so the project can become more permanent. Closed-source tools can always be stopped if the maintainer can no longer support the project. Open source is something that can always be maintained.

Ada & Zangemann has a political bent to it, but it is not wrong. Free software and open source are important and honestly need to be protected. This story helps spread that message in an approachable way, and I think is definitely worth a read for both kids and adults. After reading it with my son, he immediately started planning what he wanted to invent.

More info about the story can be found here: https://fsfe.org/activities/ada-zangemann/index.en.html


PHP with S3

 


This blog and video runs through getting started with PHP and S3. The subsequent code is all open source in the GitHub page located at the below link.

https://github.com/JoeMrCoffee/yourS3objects

Previously we looked at MinIO using it's console and UI, as well as quick set up in docker. This is a slightly more advanced look at interacting with object storage from a programmatic standpoint. 

PHP has an open SDK to tie in with S3 object storage that is provided by AWS. The video, as well as the source code in GitHub installs the SDK as part of the Docker bring up and build. This is done in the Dockerfile, and is very similar to installing the MongoDB packs required to make a PHP connection to a MongoDB database. 

From the code all the connection information to the S3 object store is in the 'header.php' file. If one wanted to use this site, or just its source code, they could also adjust the endpoint to the appropriate values. The 'header.php' file gets included in all the subsequent pages using the PHP include command, so everything else will follow the values in the header.php file.

The video talks a bit about the usefulness of the site. I developed it mostly as a reference for how the SDK could be used, but the actual site might be useful as a quick way for teams to just store and manage files in a particular bucket that only the admin or host could adjust.

Some more useful reference is below:

The 'sed' command in Linux

So I am building a new project involving PHP and S3 object storage, and as part of the solution I am looking at adjusting some of the defaults in the PHP configuration. This is not too hard to do with interactive commands, but a bit more complex when scripting the solution in a Dockerfile for automated install.

First hurdle: The docker image doesn't have a text editor. No nano, no vi, no nothing. This is actually a security measure. The general rule with containers is to make them as small as possible to keep the images small, but also improve security - the less on the server, the less can go wrong or get used the wrong way.

Second hurdle: Replacing a couple of lines of text in the php.ini file. 

Here is where 'sed' comes in.

When learning how to pipe or append data to a file I've often used | tee, or > or >> to send data to a file. 

Example:

$echo "some random text" > test.txt

That would create a file called test.txt with the 'some random text' as the content of the file. 

To append you can use the >> flag. Building on the previous example:

$echo "some more random text" >> test.txt

This adds to the file like below. 

some random text
some more random text

That is all fine, and works in the PHP containers from Docker Hub. However, if one uses the example php.ini files - php.ini-development or php.ini-production some of the values are written already. 

Here is where the 'sed' command can be employed. 

We have a very long config file with a bunch of comments and several settings that PHP can use to overwrite or adjust the defaults. In my case I want to change the default upload file size from 2M to something larger. With a text editor it is pretty easy to just search for that line and change it. To do this automatically, 'sed' is perfect. 

The syntax for substituting a line of text with sed is as below:

sed 's/<original text>/<replacement text>/' <file to change>

An example, if a file has the phrase 'some random text' we can change the sed output to 'some more text' with the below command.

sed 's/random/more/' filename

The output would be 'some more text'. 

IMPORTANT: 'sed' just changes the output, but it does not change the information in the file. To insert the changes to the file use the '-i' flag.

For example, if I wish to permanently replace the word 'random' with the word 'more', I would change the previous command to something like the following:

sed -i 's/random/more/' filename

This is a super useful command that honestly doesn't get a lot of attention, at least not in my decade plus of putzing around with Linux. Again really useful for scripting and I should have an example build in another couple of weeks.

A look at Snaps

 


Snaps are another way that developers package applications to make them installable in Linux.  Simlar to Flatpaks they are sandboxed and typically - though they don't have to be - used to run desktop applications on the Linux desktop. 

Snaps leverage the SquashFS file system which compresses the software for smaller footprints when installed on devices. When run the packages are uncompressed and mounted - shown in the video when running the 'df -alh' command. Because of the decompression needed when starting the application, sometimes the start up is a tad slower which is also shown in the video.

Snaps have had some controversy because the Snap store is hosted by Canonical and mirrors are not allowed. This organization is done for security, but there are members in the open source community who fundamentally resist this dynamic. Flatpaks would be the major alternative, though similarly, in practice, most flatpaks are hosted in a single instance in Flathub. 

More information about Snaps and contributing located below.

https://snapcraft.io/

https://en.wikipedia.org/wiki/Snap_(software)

Package managers: Flatpak - Linux Desktop Applications


 

Flatpak is quickly becoming the best way to get Linux desktop applications up and running on a Linux PC. Flatpak applications operate in a sandbox with their own images and environments that download and mirror the existing system in an isolated environment. Once installed, the applications themselves offer a responsive, essentially native experience.

Case in point, all my work requires me to use Google Chrome, Slack, and occasionally Signal on my Linux desktop. All of these can run as Flatpak applications, and in some cases perform even better or more reliably as a Flatpak install vs a native desktop client. 

When first installing Flatpaks, there is some overhead. When installing, if there is a specific environment - say a graphics driver / library - required, than the application will list it as an additional download. This can eat away at disk space versus a native application, but often it is trivial in the long run given the size of modern disk drives, and the fact that most of these environments will be re-used by other applications overtime. 

While not terribly in depth, the above video seeks to demonstrate quickly the different ways for getting started with Flatpaks, how to use the command line interface, and hopefully how to better use Flatpaks to get up an running with Linux on the desktop (i.e. a computer with point and click, not just a terminal).

More information:

https://flatpak.org/

https://docs.flatpak.org/en/latest/basic-concepts.html

Good info from System76

More specific permission settings that may be needed with certain Flatpaks

Turn down gamma in Linux under X11

 I purchased a second hand computer recently, an old Thinkpad X280, which is perfectly fine for most all of my needs. Only problem is the screen is awful. 

In an effort to slightly modify the contrast I found that there is a command in Linux under X11 (x-server is the traditional image renderer in Linux, so this may not work if your distro is using the new Wayland compositor). The command is xgamma. 

Example:

~$xgamma -gamma 0.7 


The above will reduce the gamma of the screen by 30% according to the X11 compositor. To make the changes stick, one can update the hidden file .profile in his/her home directory with the following:

xgamma -gamma 0.7 &> /dev/null

The &> /dev/null basically captures any would be output that results from the setting and throws it to /dev/null - basically throws it away. This is useful because otherwise there is an annoying "Okay to proceed" notice when first booting the system. 

Just another find which is available if not obvious in Linux! 

Reference:

https://linux.die.net/man/1/xgamma

https://forums.linuxmint.com/viewtopic.php?t=334249

 


Package managers: APT vs DNF

 

Here we are looking at the package managers 'apt' and 'dnf'. Both are modern and powerful tools for searching, installing, and managing the applications and packages installed in their respective Linux derivatives. Both share a lot of common commands as well, so it is very familiar to work with either. 

Not mentioned in the video, but a wonderful feature of open source software, is both work in most distributions and are not 100% relegated to those specific distros that ship with each respectively. That said, the package manager is a powerful component of a distribution, and I feel it is worth trying to learn the default tooling for each distribution one really wants to spend time with.  

This effort is part of a series I have rolling around in my noggin around package managers and their importance to the adoption of Linux by most people. I strongly feel that while they predate, and perhaps even inspired the concepts of App stores or Google Play used by mobile devices, not a lot of credit is really given to them. What makes package managers and the relevant repositories even more powerful than app stores is, because they run as commands, they can be scripted. Scripting allows more ease in management by sysadmins and others who need to work with a large fleet of devices. 

Before App stores, Linux was always safer then Windows primarily because software was curated for the distribution of choice. Installed packages, so long as they were coming from the package manager and the associated, known-good repos, had, and continue to have, way less risk than just going to websites and downloading software to run on a Windows PC. Package managers are faster, more reliable, and safer than what many people use to install and manage software on their computing devices, making learning them very important. 

Hopefully with just a few simple commands like 'apt update', 'apt upgrade', 'dnf update', 'apt install <whatever package you want in the repo>', and 'apt remove <installed package you do not want>', etc. new users can better take advantage of Linux and open source tools. 

More reference:

https://docs.fedoraproject.org/en-US/quick-docs/dnf-vs-apt/

https://en.wikipedia.org/wiki/APT_(software)

https://en.wikipedia.org/wiki/DNF_(software)


Minio in an Alpine Linux VM

 


Alpine is a really nice, really light Linux distribution that is often use as the base for a lot of containerized applications. This video demonstrates how to create an appliance-like VM with a minimal Alpine install to run Minio from boot. 

All of the steps aside from running the start up command using cron are in the documentation below. It is truly very simple to get working in Alpine if you just need something simple to act as an S3 object store with HTTP/HTTPS file sharing capabilities. 

A couple of mistakes in the videos are there because by copying the commands from the documentation I forgot to adjust the start up and cron commands to the directory we gave it. This is why at minute 5:50 I am checking the wrong directory and the new directory is shown (miniodata vs minio). Overall it is pretty simple and perhaps the mkdir command can be skipped depending on your preference.

References:

For the basic setup on Linux:
https://min.io/docs/minio/linux/index.html

For Debian/Ubuntu or RedHat/CentOS/Fedora installs:
https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-single-node-single-drive.html 

If there are any questions, please let me know in the comments. 

Upgrading Nextcloud in Docker

 

This is a quick post on updating and maintaining a Docker install of Nextcloud. I have had my install pretty much untouched since I first put it up about a year or two ago. The whole time it's been fine, but I heard about performance improvements in later versions and have begun the process of upgrading the service. 

Here are some steps to check for. 

Based on my previous restore experience, I know that going from one version of docker to the next can sometimes be version dependent. What has worked in managing the upgrades is to upgrade one version at a time. 

To do this, first check what Nextcloud describes as the newest version. Enter the system as the 'admin' user, go to 'Settings' -> 'Overview'. A screen like below should show.


Nextcloud will give a few suggestions of areas to make your instance more secure or highlight any issues (this is a private instance without HTTPS, as noted, and without a lot of the Calendar and other apps), and it will display what the next version is. 

That next version will be the upgrade target for the Docker instance.

In your host, you can first pull the new Docker image of Nextcloud by running:

sudo docker image pull nextcloud:<the target version from the UI>

This will save some time in the upgrade.

Next make sure everything is saved and no one is using the containers. Stop the containers with:

sudo docker stop <nextcloud container name> <nextcloud DB container name>

In my sample docker-compose reference the command would look like:

sudo docker stop nxtcloud nxtclouddb

Then modify the docker-compose.yml file with the new image specified just downloaded. For example 25.0.3 shown below. 

app:
  image: nextcloud:25.0.3
  container_name: nxtcloud
  restart: unless-stopped

  ports

  .....

Once changed bring up the containers again.

sudo docker-compose up

Here I omit the -d for running in the background. This offers a terminal view of the upgrade similar to below.


Give that a few minutes, and then the Nextcloud should be upgraded to the new version. 

To ensure the containers can be run in the background without an active terminal, stop the containers again, and re-run the sudo docker-compose up -d with the -d flag.

Some more information about Nextcloud is throughout the blog - just click on the Overview page or search by the Nextcloud tags on the right-hand side. 

For more information about the reference docker-compose to get started with it and a MariaDB instance check out the source in GitHub.