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!
Showing posts with label Podman. Show all posts
Showing posts with label Podman. Show all posts

Backing up MongoDB

Explored in previous posts and videos, MongoDB is a great way to store information without a schema. All of the information is stored in a JSON like format called BSON which essentially are documents, but similar to a SQL Database the data cannot be directly read on the host system. 

I was interested in learning some more about how to backup the files. Turns out that MongoDB provides a dump tool similar to MySQL called mongodump and mongorestore

To get started one can run the following command on their host system or container. If you used the MongoDB Docker image, the mongodump command can be run inside the container directly. 

Local Run

mongodump -u=<user> -p=<password> --authenticationDatabase=admin --db=<database to download>

The part '--authenticationDatabase' is important. On the MongoDB container the users allowed to access the database are specified are in that 'admin' database on the Mongo instance, and it must be defined in the mongodump command for the connection to be successful.

Similar to mysqldump, the mongodump command can also be used from a remote host.

Install the MongoDB Command Line Database Tools on the remote host. They offer the tools for Windows, Linux, and MacOS. 

*Note on Fedora 36, using the RedHat/CentOS 8.0 package worked. *

Modify the previous command to the below:

Remote Run

mongodump --host=<Domain/IP> --port=<Mongo service port - default is 27017> -u=<user> -p=<password> --authenticationDatabase=admin --db=<database to download>

Assuming a connection can be made all of the database files and relevant metadata will come down to the directory where the command was run. A successful run will look similar to the below. 

Once complete you will see a directory called 'dump' with the database(s) listed as directories inside. 

To specify the output location on the local system (the system being used to access and backup the MongoDB instance) you may use the '-o' or '--output' flag. 

Remote Run | Specify Download Location

mongodump --host=<Domain/IP> --port=<Mongo service port> -u=<user> -p=<password> --authenticationDatabase=admin --db=<database to download> -o=<directory location>

Restoring data from a Mongodump

The companion utility to mongodump is mongorestore. Mongorestore works similarly to mongodump, but the user specifies the db and the back up files. 

mongorestore --host <Domian/IP:Port> --authenticationDatabase=admin -u <user> -p <password> -d <db to restore> <backup folder location>

One additional tip: 

If the container was installed using the same docker-compose from the PHP and MongoDB tutorial, the port for the MongoDB Instance isn't exposed on the local system. This is good from a security standpoint. The companion web server accesses using the hostname from the private Podman / Docker network. To access the container host from the physical machine you need to use the IP address of the MongoDB container itself.

Using either Docker or Podman, run the inspect command to check to find the Network information. 

sudo podman inspect <container name or ID> | grep "IPAddress" OR
sudo docker inspect <container name or ID> | grep "IPAddress"

Additional information:

Information about using mongodump

Information about using mongorestore

Firewalld and Podman - Protecting Your DB

 

The above output is an interesting discovery I found with the relationship between Podman and Firewalld (aka firewall-cmd). 

So I was tinkering with a semi-production environment that is a web server with Apache and PHP on it, and a MySQL database running as a container. This was originally just done quickly, but is becoming more and more important. Honestly, long term, I may want to just move the database to an actual VM that has all the bells and whistles - like Cron for scheduled backups, etc. I digress.

The point is I was reading an article that a lot of sites have MySQL databases without SSL. If you run your database in a container, there is a good chance it also doesn't have SSL since most Docker images do not include that out-of-the-box. I personally don't think it is a problem if the service is on a truly internal network, but I ran a Telnet check from a remote system and it responded. Holy ^$%%@#$!

Now the port shouldn't be exposed, the firewall-cmd rules for the external interface don't allow that port type. However, with further testing I was able to connect a phpmyadmin to that host from a completely remote system. Holy#$%^&*&^%$!

What happens is on RedHat / CentOS / Fedora, podman essentially knows about firewall-cmd and spins itself into the zone trusted. You get that source and everything is available from that source. This also allows the outside world to come to that port - which is NOT what we want.

Turns out though, that it is relatively straightforward to lock this down.

Backup all the databases using a mysqldump - or in this case just by using a PHPMyAdmin to export. 

Then destroy the current container. Run the following:

podman stop <DB container name>

podman rm <DB container name>

Assuming the container has its /var/lib/mysql directory mounted to the host using the -v or --volume at creation likely the backups won't need to be restored. Just re-run the container creation command (example below).

podman run -d --name mySQLdb -v <host directory>:/var/lib/mysql -p 127.0.0.1:3306:3306 --restart=unless-stopped -e MYSQL_ROOT_PASSWORD=<password> -e lower_case_table_names=1 mysql:5.7

The difference in the above command is that the localhost IP - 127.0.0.1 - is specified along with the port value. As such, the container is now only reachable by services or other containers running on the local system. 

Now testing with a telnet command to that host with port 3306 shows unreachable, but the local web server can still interact with the database. 

telnet: Unable to connect to remote host: No route to host

Most tutorials and explanations about Docker or Podman or containers in general usually cover the "-p" call as a network port. However, it can also be used to bind a specific IP:portnum which is very important to helping protect a system that is running on the Internet. 

I hope this can help others keep themselves safer when using containers in production.

Yet another LAMP stack build - Podman!

 

No video this time, just steps. 

After getting tired of LinuxMint (the update from 19.3 to 20.04 didn't work right), I switched back to Fedora. Originally I switched from Fedora to LinuxMint to try it out thinking it would be more stable. Thus far...  nope, but it's my fault for buying a laptop with an AMD CPU. Ubuntu would likely be the better more stable desktop choice, but I prefer flatpak to snapd, and my desktop already runs Ubuntu. Ubuntu is solid, just why stick to only one distro? 

I digress. 

This blog is focused on running a LAMP stack with Podman. I mentioned it briefly in the Intro to Virtualization and Containers video, but essentially Podman is the more open source version of Docker-CE and works almost - key word there - like Docker. However, it doesn't officially have a feature like Docker Compose to build a whole bunch of containers via a yaml file - they need to be built and connected manually...

The nice thing about Podman is that it supports the latest CGroups, and is preinstalled on Fedora (some more background). Fedora 32, by default, doesn't actually support Docker because Docker does not yet support the new CGroups. So Podman is essentially more up-to-date, potentially more secure, and much more of a headache to setup.

Let's get into it.

Need to create a network for the podman containers- default doesn't seem to have a DNS as I understand.

sudo podman network create  <-- Likely better to give a name at the end, just type a name as I understand.

sudo podman network ls <-- Find the name; in the below it's cni-podman1 which is a default name when none is given.

MySQL container

Run sudo podman run --name=mysqltest -p=3306:3306 -d --network=cni-podman1 -e MYSQL_ROOT_PASSWORD=mysqltest -e lower_case_table_names=1 mysql:5.7

Note: The run command in Docker/Podman is very similar. We give the container a name, map ports  <host>:<container>, -d is detach so the container doesn't eat your terminal, define networking, then -e is environment variables like defined in the YAML file. At the end we name the image to pull from; if not already installed this will automatically pull from docker.io, though podman searchs the RedHat and CentOS image hubs first.

PHPMYADMIN container

Run sudo podman run --name=PHPMAtest -p=8081:80 --network=cni-podman1 -e MYSQL_ROOT_PASSWORD=mysqltest -e PMA_HOST=mysqltest -e PMA_PORT=3306 -d phpmyadmin/phpmyadmin:latest

Open the browser and go to localhost:8081, upon seeing PHPMyAdmin use username: root and the password as defined, in this case mysqltest. This should work if your Podman networking is set properly, and no awkward firewall rules.

PHP / Apache image

Create a directory Podman-LAMP and a sub-directory src under it (any name for either directory will do so long as your commands are consistent). Under Podman-LAMP create a Dockerfile with the below information information. 

FROM php:7.0-apache
        RUN docker-php-ext-install mysqli
        EXPOSE 80

Like in Docker, Podman recognizes Dockerfile and will build the container image based on the supplied parameters. We first build the container in order to install the mysqli, and allow port 80 <- port 443 may also be needed if you require HTTPS. We are building the container rather than just running it because we want to install mysqli and expose port 80.

Run chmod -R 755 src to allow the Apache server access to files in the src directory.

To build the new image run sudo podman build ./Podman-LAMP --tag apachephppod. The --tag option gives the image a name.

Run the PHP / Apache container

Run sudo podman run --name=APpod -v ./Podman-LAMP/src:/var/www/html:z -p 80:80 --network=cni-podman1 -d apachephppod  

**The :z in the mount command is important for SELinux issues - Docker doesn't have those issues in my experience could also be related to the CGroups and versioning that I've tried. That said other users have mentioned the :z with Docker and SElinux and could be that my previous experience of running Docker on Fedora had yet to enable the latest SELinux functionality.

Once all of that is setup you can connect to the database using msqli and set the MySQL host name as the name of the MySQL container - mysqltest in this example. This can be done in place of the IP of the local host or Docker network though it might work as well. 

Example: $mysqli = new mysqli('mysqltest', 'root', 'password', 'joescoffee');

Where: (<host address/host name>, <user>, <password>, <database>)


With everything created, to stop/start the containers just follow the below commands. Information will be retained because the containers have been named, and the Apache/PHP container has a mapped volume. If you run the run command again it will throw an error since the container with that name exists, and if you keep running run with new names it just keeps adding containers.

sudo podman container start mysqltest APpod PHPMAtest

sudo podman container stop mysqltest APpod PHPMAtest


This was a good exercise for myself. Learning how to connect separate containers together helped reinforce a lot of my understanding about the technology, both Docker and Podman. The SELinux requiring :z threw me the most, but thankfully poking around Google and forum threads pointed me in the right direction. I hope this blog can help save you the hours I spent getting it working.