Applications


Rough notes on setting up an Ubuntu server with docker

Static IP

First, we set up a static IP to our Ubuntu server using netplan. To do so, we created the following file:

/etc/netplan/01-netcfg.yaml

using the following command

sudo nano /etc/netplan/01-netcfg.yaml;

and added the following content to it:

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0f0:
      dhcp4: no
      addresses: [192.168.45.13/24]
      gateway4: 192.168.45.1
      nameservers:
          addresses: [1.1.1.1,8.8.8.8]

To apply the changes, we executed the following:

sudo netplan apply;

Update everything (the operating system and all packages)

Usually, it is a good idea to update your system before making significant changes to it:

sudo apt update -y; sudo apt upgrade -y; sudo apt autoremove -y;

Install docker

In this setup we did not use the docker version that is available on the Ubuntu repositories, we went for the official ones from docker.com. To install it, we used the following commands:

sudo apt-get install ca-certificates curl gnupg lsb-release;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg;
echo   "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null;
sudo apt-get update;
sudo apt-get install docker-ce docker-ce-cli containerd.io;

Install docker-compose

Again, we installed the official docker-compose from github.com instead of the one available in the Ubuntu repositories. At the time that this post was created, version 1.29.2 was the recommended one:

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose;
sudo chmod +x /usr/local/bin/docker-compose;

Increase network pool for docker daemon

To handle the following problem:

ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

We created the following file,

/etc/docker/daemon.json

using the command:

sudo nano /etc/docker/daemon.json;

and added the following content to it:

{
  "default-address-pools": [
    {
      "base": "172.80.0.0/16",
      "size": 24
    },
    {
      "base": "172.90.0.0/16",
      "size": 24
    }
  ]
}

We executed the following command to restart the docker daemon and get the network changes applied:

sudo systemctl restart docker;

Gave access to our user to manage docker

We added our user to the docker group so that we could manage the docker daemon without sudo rights.

sudo usermod -aG docker $USER;

Deploying

After we copied everything in place, we executed the following command to create our containers and start them with the appropriate networks and volumes:

export COMPOSE_HTTP_TIMEOUT=120;
docker-compose up -d --remove-orphans;

We had to increase the timeout as we were getting the following error:

ERROR: for container_a  UnixHTTPConnectionPool(host='localhost', port=None): Read timed out. (read timeout=60)
ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug information.
If you encounter this issue regularly because of slow network conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher value (current value: 60).

Stopping all containers using a filter on the name

docker container stop $(docker container ls -q --filter name=_web);

The above command will find all containers whose names contain _web and stop them. That command is actually two commands where one is nested inside the other.

#This command finds all containers that their name contains _web, using the -q parameter, we only get back the container ID and not all information about them.
docker container ls -q --filter name=_web;
#The second command takes as input the output of the nested command and stops all containers that are returned.
docker container stop $(docker container ls -q --filter name=_web);

Free dial-in to WebEx

The following video demonstrates how to dial into a WebEx online meeting without using the WebEx client.

In some countries, there are no toll-free numbers for people to call. Not having toll-free numbers can be problematic for people with issues with their connection or the WebEx client is not working for them.

From our experience, we noticed that there is usually a US-based toll-free number available for most WebEx meetings (a cheaper package for the owner, maybe). Considering some people’s problems and the US-based toll-free number, we propose dialing in to the meeting via Viber.

Viber offers a service called “Viber Out.” This service allows you to phone call almost anywhere globally as if you were performing a local call (so you get lower rates).

Our proposal is the following since WebEx offers toll-free numbers for the US, then use “Viber Out” to perform that free call and join your meeting. To the best of our knowledge, Viber should not charge you as their partners should not charge them for this call.

Hope it helps; it helped us!

We cannot be sure if Viber will change its policy in the future, so be sure to check where and when you use your financial tools.


ERROR: for container_a UnixHTTPConnectionPool(host=’localhost’, port=None): Read timed out. (read timeout=60)

There is this docker server that we have access to, which probably due to lousy planning, we put way too many containers on it. The server does not have SSD disks, and for that reason, whenever there are too many IO operations, it becomes unresponsive. When we mass update all containers by updating the images using the following command and then issuing a fresh docker-compose, we get a lot of time-out errors.

The commands we use to update the images and recreate our containers using the new images are the following:
(Please note that these commands need to execute from the folder where the file docker-compose.yml resides)

#Update all docker images that have the 'latest' tag
docker images --format "{{.Repository}}:{{.Tag}}" | grep ':latest' | xargs -L1 docker pull;
#Rebuild all containers using the new images.
docker-compose up -d;

After executing the second command, we often get many copies of the following error:

ERROR: for container_a  UnixHTTPConnectionPool(host='localhost', port=None): Read timed out. (read timeout=60)

This error indicates that the recreate command was waiting for too long for the docker daemon to respond with no success. At the end of the output, we can see that it was waiting for 60 seconds.

At the end of the output, we get the following information and advice:

ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug information.
If you encounter this issue regularly because of slow network conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher value (current value: 60).

Following the advice, we used the following command to overwrite the value of the COMPOSE_HTTP_TIMEOUT variable to a more significant number.

#Increase timeout period to 120 seconds.
export COMPOSE_HTTP_TIMEOUT=120;
#Rebuild all containers using the new images.
docker-compose up -d;

Doing so, we were able to rebuild all containers without reissuing many times the up command.

Sidenote

This server really does have a lot of containers, we had to create the file /etc/docker/daemon.json so that we would have enough network addressing space to handle all the bridges and sub-networks.

The contents of /etc/docker/daemon.json are:

{
  "default-address-pools": [
    {
      "base": "172.80.0.0/16",
      "size": 24
    },
    {
      "base": "172.90.0.0/16",
      "size": 24
    }
  ]
}

The above configuration solved the following problem for us:

ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

Docker: WARNING: Host is already in use by another container

We use docker to manage multiple instances of various tools on a server that we control. We have an Nginx server working as a reverse proxy that forwards all requests to the appropriate containers in the configuration. Sometimes, after updating the container images and recreating the containers, we get the error that ports 80 and 443 are already in use by another container. This problem can happen even if no other container asks for them.

The following excerpt demonstrates the problem as mentioned above.

[email protected]:~/docker-compose$ docker-compose up -d --remove-orphans;
Recreating container_a ... 
Recreating container_a ... done
Recreating container_b   ... done
Recreating container_c          ... 
Recreating nginx_reverse_proxy        ... error
Recreating container_d          ... done
Recreating container_e       ... done
Recreating container_f  ... done
WARNING: Host is already in use by another container

ERROR: for nginx_reverse_proxy  Cannot start service nginx_reverse_proxy: driver failed programming external connectivity on endpoint nginx_reverse_proxy (5a790ed7e1b24aa36cb88cbd3f49d306efa8fe023bf5b3312655218319f23a35): Bind for 0.0.0.0:443 failed: port is already allocated

ERROR: for nginx_reverse_proxy  Cannot start service nginx_reverse_proxy: driver failed programming external connectivity on endpoint nginx_reverse_proxy (5a790ed7e1b24aa36cb88cbd3f49d306efa8fe023bf5b3312655218319f23a35): Bind for 0.0.0.0:443 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
[email protected]:~/docker-compose$ sudo systemctl restart docker.socket docker.service;

To solve this issue, we had to restart two services using the systemctl command:

  • docker.socket
  • docker.service

Specifically, on an Ubuntu server, we used the following command:

sudo systemctl restart docker.socket docker.service;

How to reset root password in XAMPP MySQL

Recently a client got locked out of a MySQL deployment managed by a XAMPP. They requested us to reset the password for the root account. To do so, we followed the following procedure:

Using a text editor, we opened the following file, which is the MySQL configuration file:

C:\xampp\mysql\bin\my.ini

We found the section for the MySQL daemon, which starts after the line that contains the following tag:

[mysqld]

Right below the tag, we added a new line and added the following directive:

skip-grant-tables

Example of a configuration file:

[mysqld]
skip-grant-tables
port= 3306
socket = "C:/xampp/mysql/mysql.sock"
basedir = "C:/xampp/mysql" 
tmpdir = "C:/xampp/tmp"
...

The skip-grant-tables directive causes the server not to read the grant tables in the MySQL system schema and, thus, start without using the privilege system. This option gives anyone unrestricted server access to all databases.

After saving the file, we restarted the MySQL server from the XAMPP interface. This action forced the new settings to be loaded and take effect.

Next, using the command line, we connected to the MySQL server using the CLI client for MySQL:

C:\xampp\mysql\bin\mysql.exe --user=root

In the above command, we issued the mysql.exe application with only one parameter, the --user=root, which instructs the client to ignore the default login username and use root instead.

Once we activated the MySQL command line, we switched the usage to the mysql database using the following command:

USE mysql;

Using the following command, you can set the password for the root:

UPDATE user SET password = 'newPassword' WHERE user = 'root';

Note: In case you want to leave the root password blank, then you can use the following:

UPDATE user SET password = '' WHERE user = 'root';

Please note that there might be more than one entry for root in the system, as it could contain different IPs etc. To see all available options, execute the following:

SELECT * FROM user \G;

After we finished messing with the MySQL internals, we executed the following command to exit the MySQL terminal:

exit;

Then, we edited the MySQL configuration file again:

C:\xampp\mysql\bin\my.ini

We found the section for the MySQL daemon again, which starts after the line that contains the following tag:

[mysqld]

We removed our skip-grant-tables directive and saved the file.

We restarted the MySQL server via the XAMPP interface after saving the file. The restart forced the updated settings to load and take effect due to this action.

Success!! The root user had the password we set for it and we could access the database as expected.

The same guide can be used for other installations of MySQL so long you know where the MySQL configuration file is.