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/05 13:46] – [Using Podman for new containers] 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 66: Line 60:
 Overall **Podman** is much more adherent to the Linux/Unix way of doing things.  Overall **Podman** is much more adherent to the Linux/Unix way of doing things. 
  
-Installing Podman is pretty easy since it's in Portage repository, but let's enable docker wrapper:+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" +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.
-SLOT="0+
-KEYWORDS="~amd64"+
  
-DEPEND="" + 
-RDEPEND=" +==== Podman networks ==== 
-        ${DEPEND+ 
-        dev-python/pyyaml[${PYTHON_USEDEP}] +Since you want to run containers as non-root, you need to create as root the networks. My approach is to create one subnetwork for each group of containers, and each group of containers will run a non-root user. 
-        dev-python/python-dotenv[${PYTHON_USEDEP}] + 
-+To create a Podman subnet you need to run the following command after each reboot, as root: 
-BDEPEND=""+<code bash> 
 +podman network create my-container-net 
 +</code> 
 + 
 +Inside your //docker-compose.yml// you will add a new network called //my-container-net//, for eaxmple: 
 +<code> 
 +    services: 
 +   ..... 
 +    environment: 
 +    .... 
 +    ports: 
 +      - xxx:yyy 
 +    volumes: 
 +      - my-volume:/root/.config/:ro 
 +    networks: 
 +      - my-container-net 
 + 
 +.... 
 + 
 +networks: 
 +  my-container-net: {} 
 +</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. 
 + 
 + 
 +==== 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> </file>
  
-as //app-containers/podman-compose-1.0.6.ebuild// and then emerge it (see [[https://bugs.gentoo.org/717748]]).+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
  
-I hope that this ebuild will be merged to Gentoo official repo soon.+The above script also provide an "update" commnand that will update your containers automatically.
  
  
Line 134: Line 253:
   * always run Podman as unpriviledged user   * always run Podman as unpriviledged user
   * 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.
 +
 +
  
 ==== Migration from Docker to Podman ==== ==== Migration from Docker to Podman ====
Line 144: Line 266:
  > chown service:service -R /data/daemons/service  > chown service:service -R /data/daemons/service
 </code> </code>
 +
 +At this point you might want to edit the //network// part of the docker compose file according to what i wrote above.
  
 Now, most probably all you need to do is the classic (but rewritten): Now, most probably all you need to do is the classic (but rewritten):
Line 152: Line 276:
  
 and enjoy. and enjoy.
 +
 +(remember to create the network, as root)
  
 === Migrating Images Podman === === Migrating Images Podman ===
- 
  
 If you need to export your images from Docker to Podman (you don't if they are public images), as root, export all docker images relevant to your service (you can see them in the composer file), use //docker image ls// to list images and //docker save -o ...// to save each one of them as a tar file: If you need to export your images from Docker to Podman (you don't if they are public images), as root, export all docker images relevant to your service (you can see them in the composer file), use //docker image ls// to list images and //docker save -o ...// to save each one of them as a tar file:
Line 214: 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.
- +
  
 +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