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/09 10:06] 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 toowithout 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**+If you want to do things manuallyjust keen in mind that you need to ensure **nat** ip-table is loadedWhile it is not used by podman, it seems to be necessary somehow to exist
-<file - 50-service.start> +<code>
-#!/bin/bash+
 modprobe iptable_nat modprobe iptable_nat
-podman network create service-net +iptable --t nat 
-su service -c "podman compose up -d" +</code>
-</file> +
- +
-Note that unless you already load the NAT iptable module, you should do it now as it will block containers to properly start, if missing, and for some reason podman will not load it automatically. +
- +
- +
-And don'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. +
  
  

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