User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
gentoo:containers [2024/02/08 15:13] willygentoo:containers [2025/03/13 13:25] (current) – [Using Containers on Gentoo] willy
Line 1: Line 1:
-====== Using Containers on Gentoo ======+====== F) Using Containers on Gentoo ======
  
-Containers are a great tool that caters to some specific, and important, needs. But be aware that //containers// are not **the** solution to selfhosting-made-easy and, specifically, **containers havebeen created to solve different issues than self-hosting!** +Containers are a great tool that caters to some specific, and important, needs. But be aware that //containers// are not **the** solution to selfhosting-made-easy and, specifically, **containers have been created to solve different issues than self-hosting!** 
  
-Bear in mind, always, that **containers** while being an astounding piece of technology, are **NOT** meant and have **NOT** been created with self-hosting in mind. +Bear in mind, always, that **containers** while being an astounding piece of technology, are **NOT** meant and have **NOT** been created with self-hosting in mind. Since it's easy and simple to use them for self-hosting, at least let's see how to do that properly.
  
 Containerization technology can roughly be divided into two big categories: Containerization technology can roughly be divided into two big categories:
Line 15: Line 15:
   * For developers, it's easier to provide a //docker-compose.yml// rather than proper installation instruction   * For developers, it's easier to provide a //docker-compose.yml// rather than proper installation instruction
  
-But are these really positive points of containers? don't think so. The //ease of deployment// is because developers are too lazy to provide clear and nice deployment instruction or people are too lazy to read them. But this is **not the way of Linux**. //Ease of upgrade// again falls into the same objectionas well as //ease of management//, and will show you how to setup your services so that they can be installed, managed and upgraded with ease as well. I will not delve into how, for developers, it's easier to provide a docker-compose file instead of properly documenting their tools and installation procedures because it's out of scope here. +am realizing more and more the added value of using containersso have changed my mind over time. I still think there are negative points in relying on Docker for self-hosting:
- +
-Now, let's see the negative points of Docker for self-hosting:+
   * All services running as //root// (against Linux policies)   * All services running as //root// (against Linux policies)
   * Lots of duplicated services (how many postgress databases have you running around?)   * Lots of duplicated services (how many postgress databases have you running around?)
-  * You don't understand what's going on  
   * You don't learn anything new deploying your services   * You don't learn anything new deploying your services
   * When it breaks, it breaks hard because you don't know what broke   * When it breaks, it breaks hard because you don't know what broke
Line 26: Line 23:
   * It's back to Windows approach: black boxes everywhere that you can only roll-back or reinstall   * It's back to Windows approach: black boxes everywhere that you can only roll-back or reinstall
  
-Granted, all this **could** be fixed by fixing the docker images and maybe fixing your docker-compose files to improve things a bit, but who is really doing that? Wouldn't then be easier to just install on bare-metal? What would be the point in containers then? +In short, the spreading usage of Docker in the self-hosting world bring to Linux some bad practices and philosophy of the Windows world. Is this really necessary? Do we really want to become forced to be idiot-users who don't know any better? Is this really what means to be Linux users?
- +
-In short, the spreading usage of Docker in the self-hosting world bring to Linux the very worst practices and philosophy of the Windows world. Is this really necessary? Do we really want to become forced to be idiot-users who don't know any better? Is this really what means to be Linux users?+
  
 Question for your thoughts, now let's see how, at least, to use containers in a slightly better way. Question for your thoughts, now let's see how, at least, to use containers in a slightly better way.
Line 34: Line 29:
 ==== "TLDR" ==== ==== "TLDR" ====
  
-I prefer to avoid containers at all. But we are already at the point where some services are provided **only** as containers, and this is what i think the the **worse possible outcome** of this using containers more and more. **Where is the choice?** Why would i be forced to use some semi-proprietary technology to deploy Open Source services?+We are already at the point where some services are provided **only** as containers, and this is what i think the the **worse possible outcome** of this using containers more and more. **Where is the choice?** Why would i be forced to use some semi-proprietary technology to deploy Open Source services?
  
 I think that this is a trend that should be stopped. Please do provide containers and docker files, it's good and why not, but always also support bare-metal installations which means, please always provide **binary distributions** and **installation instructions** because without those, we will be nothing better than idiot-users and your service cannot be really called //open//. I think that this is a trend that should be stopped. Please do provide containers and docker files, it's good and why not, but always also support bare-metal installations which means, please always provide **binary distributions** and **installation instructions** because without those, we will be nothing better than idiot-users and your service cannot be really called //open//.
- 
  
 ===== Docker ===== ===== Docker =====
Line 68: Line 62:
 Installing Podman is pretty easy since it's in Portage repository, but let's enable docker wrapper as well, so you can "forget" you run Podman and use the //docker// command instead: Installing Podman is pretty easy since it's in Portage repository, but let's enable docker wrapper as well, so you can "forget" you run Podman and use the //docker// command instead:
 <code bash> <code bash>
- > echo "app-containers/podman wrapper" > /etc/portage/package.use/podman +echo "app-containers/podman wrapper" > /etc/portage/package.use/podman 
- emerge podman+emerge app-containers/podman
 </code> </code>
  
Line 85: Line 79:
 which i suggest to run as un-priviledged user to verify everything is working as non-root too. which i suggest to run as un-priviledged user to verify everything is working as non-root too.
  
-Now, install **podman-compose** which is bit more complex because at this time there is no official ebuild yet.+Now, install **podman-compose**, and thanks to few user contributed inputs (see [[https://bugs.gentoo.org/717748]]), mine included, it's not part of portage gentoo tree, so: 
 +<code bash> 
 +emerge -vp podman-compose 
 +</code>
  
-Follow my [[gentoo:repositories|repo guide]] to create a custom repo (or use your already existing custom repo) to add the following ebuild: +beware that it might be masked for your arch, in this case, just unmask it with your keyword, ex ~amd64.
-<file - podman-compose-1.0.6.ebuild> +
-# Copyright 2024 Gentoo Authors +
-# Distributed under the terms of the GNU General Public License v2+
  
-EAPI=8+=== Podman rootless users ===
  
-DISTUTILS_USE_SETUPTOOLS=rdepend +When running a container rootless, which is the main point behind Podman, you might end up having some issues with user IDs.
-PYTHON_COMPAT=( python3_{10..11} )+
  
-inherit distutils-r1+[[https://blog.christophersmart.com/2021/01/26/user-ids-and-rootless-containers-with-podman/|This]] article is a very good read on the topic.
  
-DESCRIPTION="Run docker-compose files without root with podman" +In shortwhen running rootless, the //user 0//, or root, of the container, will be mapped to your user ID, and any //additional// user will be remapped according to the content of **/etc/subuid** and **/etc/subgid** files. This means that if the container defines additioanl users, they will __not__ map to your user but to a different UID that is also sub-mapped to your user, but Linux itself will not recognize that and any files and folders created by the container will belog to this strange user.
-HOMEPAGE="https://pypi.org/project/podman-compose https://github.com/containers/podman-compose" +
-SRC_URI="https://files.pythonhosted.org/packages/65/a8/d77d2eaa85414d013047584d3aa10fac47edb328f5180ca54a13543af03a/podman-compose-1.0.6.tar.gz" +
-#SRC_URI="mirror://pypi/${PN:0:1}/${PN}/${P}.tar.gz" +
- +
-LICENSE="GPL-2" +
-SLOT="0" +
-KEYWORDS="~amd64" +
- +
-DEPEND="" +
-RDEPEND=" +
-        ${DEPEND} +
-        dev-python/pyyaml[${PYTHON_USEDEP}] +
-        dev-python/python-dotenv[${PYTHON_USEDEP}] +
-+
-BDEPEND="" +
-</file>+
  
-as //app-containers/podman-compose-1.0.6.ebuild// and then emerge it (see [[https://bugs.gentoo.org/717748]]).+The easiest way to fix it, is to force your container to run... **as user 0**! In fact, since we are using rootless podman, that only means **as your own user** nad not actually root.
  
-I hope that this ebuild will be merged to Gentoo official repo soon. 
  
 ==== Podman networks ==== ==== Podman networks ====
Line 127: Line 103:
 To create a Podman subnet you need to run the following command after each reboot, as root: To create a Podman subnet you need to run the following command after each reboot, as root:
 <code bash> <code bash>
- >   podman network create my-container-net+podman network create my-container-net
 </code> </code>
  
Line 147: Line 123:
 networks: networks:
   my-container-net: {}   my-container-net: {}
-  </code>+</code>
      
-  I strongly suggest that you edit your docker compose files and ensure each service has it's own independent network. I will give more details for each service on it's respective page.+I strongly suggest that you edit your docker compose files and ensure each service has it's own independent network. I will give more details for each service on it's respective page. 
 + 
 + 
 +==== Podman containers autostart ==== 
 + 
 +Autostarting containers is pretty easy if you use SystemD, but even if you don't, and i don't, it's easy enough too. 
 + 
 +<file - /etc/init.d/user-containers> 
 +#!/sbin/openrc-run 
 +# Copyright 2024 Willy Garidol 
 +# Distributed under the terms of the GNU General Public License v3 
 + 
 +depend() { 
 +        need localmount net 
 +
 + 
 +UC_LOG_PATH=/var/log/user-containers 
 +UC_SLOT="${SVCNAME#user-containers.}" 
 +UC_USER=${USER:-${UC_SLOT}} 
 +UC_COMPOSER_FILE=${COMPOSER_FILE:-docker-compose.yml} 
 +UC_CHOWN_DIR=${CHOWN_DIR} 
 +if [ "${UC_SLOT}" != "user-containers"
 +then 
 +        UC_HOME=${HOME:-$(su - ${UC_USER} -c "pwd")} 
 +fi 
 + 
 +extra_commands="update" 
 +update() { 
 +        if [ "${UC_SLOT}" != "user-containers"
 +        then 
 +                COMMAND="$(which podman)" 
 +                stop 
 +                ebegin "Running podman compose pull..." 
 +                su - ${UC_USER} -c "${COMMAND} compose -f ${UC_COMPOSER_FILE} pull" 
 +                start 
 +        else 
 +                ebegin "Error: do not run this script, run a link to it!" 
 +                eend 255 
 +        fi 
 +
 + 
 +description=${DESCRIPTION:-You forgot to describe your container} 
 +pidfile="/run/${RC_SVCNAME}.pid" 
 + 
 +start_pre() { 
 +        if [ "${UC_SLOT}" != "user-containers"
 +        then 
 +                test -e "${UC_LOG_PATH}" || mkdir "${UC_LOG_PATH}" 
 +                test -e "${UC_LOG_PATH}/${UC_SLOT}" || { 
 +                        mkdir "${UC_LOG_PATH}/${UC_SLOT}" 
 +                } && chown -R ${UC_USER} "${UC_LOG_PATH}/${UC_SLOT}" 
 +                if [ -n "${UC_CHOWN_DIR}" -a -e ${UC_CHOWN_DIR} ] 
 +                then 
 +                        chown -R ${UC_USER} ${UC_CHOWN_DIR} 
 +                fi 
 +        else 
 +                ebegin "Error: do not run this script, run a link to it!" 
 +                eend 255 
 +        fi 
 +
 + 
 + 
 +start() { 
 +        ebegin "Starting container '${UC_SLOT}' for user '${UC_USER}' (${UC_HOME})" 
 +        COMMAND="$(which podman)" 
 +        ARGUMENTS=(compose -f ${UC_COMPOSER_FILE} up) 
 +        ebegin " ... ensuring nat table is loaded ..." 
 +        iptables -L -t nat &> /dev/null 
 +        ebegin " ... creating '${UC_SLOT}-net' ..." 
 +        podman network create ${UC_SLOT}-net &> /dev/null 
 +        su - "${UC_USER}" -c "$(which podman) compose down" &> /dev/null 
 +        start-stop-daemon -p ${pidfile} \ 
 +                          -1 "${UC_LOG_PATH}/${UC_SLOT}/${UC_SLOT}.out.log"
 +                          -2 "${UC_LOG_PATH}/${UC_SLOT}/${UC_SLOT}.err.log"
 +                          -u ${UC_USER} \ 
 +                          -d ${UC_HOME} \ 
 +                          -b -m \ 
 +                          --start  "${COMMAND}"
 +                          -- ${ARGUMENTS[@]} 
 +        eend $? 
 +
 + 
 +stop() { 
 +        ebegin " ... running 'podman compose down' ..." 
 +        su - "${UC_USER}" -c "$(which podman) compose -f ${UC_COMPOSER_FILE} down" &> /dev/null 
 +        start-stop-daemon -p ${pidfile} \ 
 +                          -u ${UC_USER} \ 
 +                          -d ${UC_HOME} \ 
 +                          --stop ${UC_SLOT} 
 +        eend $? 
 +
 +</file> 
 + 
 +I assume you have a**service_name** that runs with a podman compose file as user **myuser**. 
 + 
 +Just link the above script to your new service file: 
 +<code bash> 
 +ln -s /etc/init.d/user-containers /etc/init.d/user-containers.service_name 
 +</code> 
 + 
 +and create  simple configuration file with user name and description in it: 
 +<file - /etc/conf.d/user-containers.service_name> 
 +USER=myuser 
 +DESCRIPTION="my containerized service" 
 +</file> 
 + 
 +and add the service to your desired runlevel: 
 +<code bash> 
 +rc-update add user-containers.service_name default 
 +</code> 
 + 
 +That's it.  
 + 
 +The above script also provide an "update" commnand that will update your containers automatically. 
  
 ==== Using Podman for new containers ==== ==== Using Podman for new containers ====
Line 164: Line 254:
   * Podman containers are not restarted at boot: i will give you instructions for those services as needed.   * Podman containers are not restarted at boot: i will give you instructions for those services as needed.
   * Networks needs to be explicitly declared and created as root.   * Networks needs to be explicitly declared and created as root.
 +
 +
  
 ==== Migration from Docker to Podman ==== ==== Migration from Docker to Podman ====
Line 247: Line 339:
 This can be made permanent in **/etc/sysctl.d**. This can be made permanent in **/etc/sysctl.d**.
  
-- Podman containers are not restarted at boot. To achieve the same behaviour as Docker, my suggestion is to create a startup file under **/etc/local.d/** where you **su** as your unpriviledged user and simply do a **podman compose up**, that's it. +- Podman containers are not restarted at boot. To achieve the same behaviour as Docker, my suggestion is to follow my lead on leveraging //local.d// with [[gentoo:locald|Custom User Services]] where i show you how i manage very easily to auto-start containers at boot and properly shut them down too, without writing a single line of script.
- +
-An example for a service //service// owned by user //service// which required //service-net// network , your **/etc/local.d/50-service.start**: +
-<file - 50-service.start> +
-#!/bin/bash +
-podman network create service-net +
-su - service -c "podman compose up -d" +
-</file> +
- +
-And don't forget a **/etc/local.d/50-service.stop** file as well to ensure the service is stopped properly+
-<file - 50-service.stop> +
-#!/bin/bash +
-su - service -c "podman compose down+
-</file> +
- +
-Remember to set both scripts are **+x** permission.+
  
 +If you want to do things manually, just keen in mind that you need to ensure **nat** ip-table is loaded. While it is not used by podman, it seems to be necessary somehow to exist:
 +<code>
 +modprobe iptable_nat
 +iptable -L -t nat
 +</code>
  
  

This website uses technical cookies only. No information is shared with anybody or used in any way but provide the website in your browser.

More information