From 556ade43b0b6b3a12121aa1fe6cfda9d1a8a3dc9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 11:10:20 +0000 Subject: [PATCH] deploy: 4eaed9e0b7435926dcc347dbc2884b406789151f --- 404.html | 4 ++-- assets/js/{38a042e4.3acae315.js => 38a042e4.3e9357ca.js} | 2 +- assets/js/{b2f554cd.a2d1b4be.js => b2f554cd.71472b0f.js} | 2 +- .../{runtime~main.f2735a76.js => runtime~main.03da001e.js} | 2 +- blog.html | 4 ++-- blog/archive.html | 4 ++-- blog/atom.xml | 2 +- blog/develop-using-devcontainer.html | 6 +++--- blog/feed.json | 2 +- blog/podman-desktop-release-0.10.html | 4 ++-- blog/rss.xml | 2 +- blog/tags.html | 4 ++-- blog/tags/codespaces.html | 4 ++-- blog/tags/devcontainer.html | 4 ++-- blog/tags/kubernetes.html | 4 ++-- blog/tags/podman-desktop.html | 4 ++-- blog/tags/release.html | 4 ++-- core-values.html | 4 ++-- docs/Installation.html | 4 ++-- docs/Installation/linux-install.html | 4 ++-- docs/Installation/macos-install.html | 4 ++-- docs/Installation/windows-install.html | 4 ++-- docs/getting-started/getting-started.html | 4 ++-- docs/intro.html | 4 ++-- docs/podman-compose.html | 4 ++-- docs/tags.html | 4 ++-- docs/tags/getting-started.html | 4 ++-- docs/tags/podman-desktop.html | 4 ++-- docs/troubleshooting.html | 4 ++-- downloads.html | 4 ++-- downloads/linux.html | 4 ++-- downloads/macOS.html | 4 ++-- downloads/windows.html | 4 ++-- extend.html | 4 ++-- features.html | 4 ++-- index.html | 4 ++-- search.html | 4 ++-- 37 files changed, 69 insertions(+), 69 deletions(-) rename assets/js/{38a042e4.3acae315.js => 38a042e4.3e9357ca.js} (71%) rename assets/js/{b2f554cd.a2d1b4be.js => b2f554cd.71472b0f.js} (82%) rename assets/js/{runtime~main.f2735a76.js => runtime~main.03da001e.js} (97%) diff --git a/404.html b/404.html index 8534325f797..73452db8657 100644 --- a/404.html +++ b/404.html @@ -10,13 +10,13 @@ - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/38a042e4.3acae315.js b/assets/js/38a042e4.3e9357ca.js similarity index 71% rename from assets/js/38a042e4.3acae315.js rename to assets/js/38a042e4.3e9357ca.js index 16791800f7c..ad7d3455d5f 100644 --- a/assets/js/38a042e4.3acae315.js +++ b/assets/js/38a042e4.3e9357ca.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7138],{5318:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>m});var a=t(7378);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},d=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),u=p(t),m=o,h=u["".concat(l,".").concat(m)]||u[m]||c[m]||r;return t?a.createElement(h,i(i({ref:n},d),{},{components:t})):a.createElement(h,i({ref:n},d))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var r=t.length,i=new Array(r);i[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:o,i[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var a=t(2685),o=(t(7378),t(5318));const r={title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",slug:"develop-using-devcontainer",authors:["benoitf"],tags:["podman-desktop","devcontainer","codespaces"],hide_table_of_contents:!1},i=void 0,s={permalink:"/blog/develop-using-devcontainer",source:"@site/blog/2022-11-17-develop-podman-using-codespaces.md",title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",date:"2022-11-17T00:00:00.000Z",formattedDate:"November 17, 2022",tags:[{label:"podman-desktop",permalink:"/blog/tags/podman-desktop"},{label:"devcontainer",permalink:"/blog/tags/devcontainer"},{label:"codespaces",permalink:"/blog/tags/codespaces"}],readingTime:6.985,hasTruncateMarker:!0,authors:[{name:"Florent Benoit",title:"Maintainer of Podman Desktop",url:"https://github.com/benoitf",imageURL:"https://github.com/benoitf.png",key:"benoitf"}],frontMatter:{title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",slug:"develop-using-devcontainer",authors:["benoitf"],tags:["podman-desktop","devcontainer","codespaces"],hide_table_of_contents:!1},prevItem:{title:"Release Notes - Podman Desktop 0.10",permalink:"/blog/podman-desktop-release-0.10"}},l={authorsImageUrls:[void 0]},p=[{value:"Defining image of the container",id:"defining-image-of-the-container",level:2},{value:"Configure the DevContainer using devcontainer.json",id:"configure-the-devcontainer-using-devcontainerjson",level:2},{value:"Using the DevContainer.json on Github Codespace",id:"using-the-devcontainerjson-on-github-codespace",level:2},{value:"Conclusion",id:"conclusion",level:2}],d={toc:p};function c(e){let{components:n,...r}=e;return(0,o.kt)("wrapper",(0,a.Z)({},d,r,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"GitHub ",(0,o.kt)("a",{parentName:"p",href:"https://github.blog/changelog/2022-11-09-codespaces-for-free-and-pro-accounts/"},"announced last week")," that Codespaces is available for everyone and it includes free minutes."),(0,o.kt)("p",null,"Let see how we can use a ",(0,o.kt)("a",{parentName:"p",href:"https://containers.dev/"},"Development Container")," having all the tools to build and run Podman Desktop. The Development Container works locally using Visual Studio Code but in this blog post we will see how it works directly with a simple click from GitHub."),(0,o.kt)("p",null,"The challenges are to run a desktop tool (Podman Desktop) and running a container engine (Podman) inside this Development Container without using too many memory !"),(0,o.kt)("h2",{id:"defining-image-of-the-container"},"Defining image of the container"),(0,o.kt)("p",null,"The first thing is in the choice of the image for the container. It is possible to pick-up a default image and add some features but there is no existing feature for Podman at ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/devcontainers/features/tree/main/src"},"https://github.com/devcontainers/features/tree/main/src")," and most of the features are expecting to run on top of Debian/Ubuntu"),(0,o.kt)("p",null,"If you are not interested in how to setup the image, jump to the ",(0,o.kt)("a",{parentName:"p",href:"#configure-the-devcontainer-using-devcontainerjson"},"next section"),"."),(0,o.kt)("p",null,"Podman binaries are available quickly after the releases for Fedora. I decided then to use ",(0,o.kt)("inlineCode",{parentName:"p"},"Fedora 37")," as the base image."),(0,o.kt)("p",null,"Let start the Containerfile using:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"FROM quay.io/fedora/fedora:37\n")),(0,o.kt)("p",null,"Then I install Node.js 16 from official nodejs.org repository. It's easier to switch to the version that we need."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},'# install Node.js + yarn\nENV NODE_VERSION 16.18.1\nRUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" && \\\n tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 && \\\n rm "node-v$NODE_VERSION-linux-x64.tar.gz" && \\\n npm install -g yarn\n')),(0,o.kt)("p",null,"Now, all system dependencies used to run an Electron application needs to be installed."),(0,o.kt)("p",null,"Podman is also installed so we can run some containers inside this container."),(0,o.kt)("p",null,"And of course, we need to install VNC (I choose ",(0,o.kt)("a",{parentName:"p",href:"https://tigervnc.org/"},"tigervnc"),") with a light Window Manager (",(0,o.kt)("a",{parentName:"p",href:"http://fluxbox.org/"},"fluxbox"),")."),(0,o.kt)("p",null,"To connect to the display of the container, we need to expose VNC over HTML/websocket using ",(0,o.kt)("a",{parentName:"p",href:"https://novnc.com/"},"noVNC")),(0,o.kt)("p",null,"xterm is installed to start a terminal from the VNC side."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"RUN dnf -y update && \\\n yum -y reinstall shadow-utils && \\\n yum install -y git \\\n # dependencies for Podman Desktop\n nss \\\n atk \\\n at-spi2-atk \\\n cups-libs \\\n gtk3 \\\n # for remote Display\n fluxbox \\\n tigervnc-server \\\n xorg-x11-fonts-Type1 \\\n novnc \\\n supervisor \\\n xdpyinfo \\\n # for podman\n podman \\\n fuse-overlayfs --exclude container-selinux \\\n xterm && \\\n rm -rf /var/cache /var/log/dnf* /var/log/yum.*\n")),(0,o.kt)("p",null,"Supervisord setup the launch of the VNC server and the Window manager"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"COPY supervisord.conf /etc/supervisord.conf\n")),(0,o.kt)("p",null,"A custom theme for fluxbox:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"COPY fluxbox /usr/share/fluxbox/init\n")),(0,o.kt)("p",null,"Then we need a special configuration to allow to have Podman working inside the container"),(0,o.kt)("p",null,"We add the ",(0,o.kt)("inlineCode",{parentName:"p"},"podman-desktop")," user with correct range on subuid and subgid when running containers. I used the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration"},"tutorial"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"RUN useradd -u 1000 podman-desktop && echo podman-desktop:10000:5000 > /etc/subuid && echo podman-desktop:10000:5000 > /etc/subgid\n")),(0,o.kt)("p",null,"Then use some default configuration files"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"# initialize conf files\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman-desktop/.config/containers/containers.conf\n")),(0,o.kt)("p",null,"and make sure that all permissions are correct following the guide ",(0,o.kt)("a",{parentName:"p",href:"https://www.redhat.com/sysadmin/podman-inside-container"},"https://www.redhat.com/sysadmin/podman-inside-container")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"# set permissions\nRUN chown podman-desktop:podman-desktop -R /home/podman-desktop && chmod 644 /etc/containers/containers.conf && \\\n mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock && \\\n mkdir -p /run/user/1000 && chown podman-desktop:podman-desktop /run/user/1000\n")),(0,o.kt)("p",null,"plus define an empty user namespace."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},'ENV _CONTAINERS_USERNS_CONFIGURED=""\n')),(0,o.kt)("p",null,"Make sure Podman will create the socket in an expected directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"# socket path for podman\nENV XDG_RUNTIME_DIR=/run/user/1000\n")),(0,o.kt)("p",null,"OK ! we have a custom Containerfile providing all the tools to build and run Podman Desktop (using VNC for the display), run Podman and run Electron."),(0,o.kt)("p",null,"The current file is available at ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile"},"https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile")),(0,o.kt)("p",null,"Let's configure the DevContainer."),(0,o.kt)("h2",{id:"configure-the-devcontainer-using-devcontainerjson"},"Configure the DevContainer using devcontainer.json"),(0,o.kt)("p",null,"DevContainer definition is stored at ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer/devcontainer.json")," file."),(0,o.kt)("p",null,"We need to reuse the image of the previous step. For that let's use the build section of the ",(0,o.kt)("inlineCode",{parentName:"p"},"devcontainer.json")," file."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"build": {\n "dockerfile": "Containerfile"\n},\n')),(0,o.kt)("p",null,"In order to avoid to redo all the build steps each time we open a workspace using this dev container, we published the image to quay.io at ",(0,o.kt)("a",{parentName:"p",href:"https://quay.io/repository/podman-desktop/devcontainer-parent?tab=tags&tag=next"},"quay.io/podman-desktop/devcontainer-parent:next\n"),". This parent image is not changing much so it's better to use is as a parent one."),(0,o.kt)("p",null,"Inside ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," directory there is a ",(0,o.kt)("inlineCode",{parentName:"p"},".parent")," directory with everything related to the parent image."),(0,o.kt)("p",null,"And in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer/Containerfile")," file we reference this image"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"FROM quay.io/podman-desktop/devcontainer-parent:next\n")),(0,o.kt)("p",null,"By default, we will be ",(0,o.kt)("inlineCode",{parentName:"p"},"root")," in the container and this is probably not what we expect. Let's change that."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"containerUser": "podman-desktop"\n')),(0,o.kt)("p",null,"Some Visual Studio Code extensions are nice to use and we can add them"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},' "extensions": ["svelte.svelte-vscode", "bradlc.vscode-tailwindcss"]\n')),(0,o.kt)("p",null,"Then here is the tricky part, how to run our container allowing to run again inside the container some containers with podman."),(0,o.kt)("p",null,"We specify the arguments to make it possible. It's possible to use ",(0,o.kt)("inlineCode",{parentName:"p"},"--privileged")," flag but I prefer to list the subset of permissions.\nUsing ",(0,o.kt)("inlineCode",{parentName:"p"},"--privileged")," we don't really know what are the privilege that are required while specifying all of them, people are aware of what is granted/denied."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"runArgs": [\n "--cap-add=sys_admin",\n "--security-opt",\n "seccomp=unconfined",\n "--device",\n "/dev/fuse",\n "--security-opt",\n "label=disable",\n "--security-opt",\n "apparmor=unconfined"\n ],\n')),(0,o.kt)("p",null,"Source code of Podman Desktop needs to be editable within the DevContainer so it needs to be mounted."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",\n"workspaceFolder": "/workspace",\n')),(0,o.kt)("p",null,"Then we need a command to build Podman Desktop."),(0,o.kt)("p",null,"For that, we use ",(0,o.kt)("inlineCode",{parentName:"p"},"onCreateCommand")," hook with a custom command"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"onCreateCommand": "${containerWorkspaceFolder}/.devcontainer/onCreateCommand.sh",\n')),(0,o.kt)("p",null,"and in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," folder the ",(0,o.kt)("inlineCode",{parentName:"p"},"onCreateCommand.sh")," script is the following"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"#!/bin/sh\nyarn\n\nMODE=production yarn run build && yarn run electron-builder build --linux --dir --config .electron-builder.config.js\n")),(0,o.kt)("p",null,"Two instructions:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"Fetch all Node.js dependencies."),(0,o.kt)("li",{parentName:"ol"},"build Podman Desktop in the ",(0,o.kt)("inlineCode",{parentName:"li"},"dist")," folder using ",(0,o.kt)("inlineCode",{parentName:"li"},"Linux")," as target Operating System.")),(0,o.kt)("p",null,"After the start of the container, how to launch Podman Desktop, the website and VNC, etc ?"),(0,o.kt)("p",null,"Just use ",(0,o.kt)("inlineCode",{parentName:"p"},"postStartCommand")," hook."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"postStartCommand": "${containerWorkspaceFolder}/.devcontainer/postStartCommand.sh",\n')),(0,o.kt)("p",null,"and in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," folder the ",(0,o.kt)("inlineCode",{parentName:"p"},"postStartCommand.sh")," script is the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},'#!/bin/sh\n\n# Start all services\n/usr/bin/supervisord -c /etc/supervisord.conf &\n\n# wait X server to be ready or after 2mn exit\necho "Waiting for X server to be ready"\ntimeout 120 bash -c \'until xdpyinfo -display :0 &> /dev/null; do printf "."; sleep 1; done\'\n\n# launch podman desktop\necho "Launching Podman Desktop"\ncd dist/linux-unpacked/&& ./podman-desktop &\n\n# Launch the 9000 redirect after 20 seconds\nsleep 20\nwebsockify --web=/usr/share/novnc localhost:9000 localhost:5900 &\n\n# launch the website rendering\necho "Launching Website"\ncd website && yarn start\n')),(0,o.kt)("p",null,"It starts VNC and noVNC, start precompiled Podman Desktop and start the documentation rendering."),(0,o.kt)("p",null,"It is not launching the Watch mode/development mode of Podman Desktop as it requires a container having more than 8GB of memory."),(0,o.kt)("p",null,"Picking up a larger instace with for example 16GB, it's possible to use development mode."),(0,o.kt)("p",null,"Of course, to make VNC happy, we need to specify the ",(0,o.kt)("inlineCode",{parentName:"p"},"DISPLAY")," environment variable."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"remoteEnv": {\n "DISPLAY": ":0"\n}\n')),(0,o.kt)("p",null,"When the DevContainer is fully available, we want to have a way to quickly open the ",(0,o.kt)("inlineCode",{parentName:"p"},"Website rendering URL")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"noVNC")),(0,o.kt)("p",null,"Let's tweak the ",(0,o.kt)("inlineCode",{parentName:"p"},"devcontainer.json")," file by adding the ",(0,o.kt)("inlineCode",{parentName:"p"},"portsAttributes")," section"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"portsAttributes": {\n "9000": {\n "label": "vnc",\n "onAutoForward": "openPreview"\n },\n "3000": {\n "label": "website"\n }\n}\n')),(0,o.kt)("p",null,"After all post-creation steps, the ",(0,o.kt)("inlineCode",{parentName:"p"},"Preview")," browser inside the VS Code editor will open a window to VNC. And another port (",(0,o.kt)("inlineCode",{parentName:"p"},"3000"),") is flagged for the website."),(0,o.kt)("h2",{id:"using-the-devcontainerjson-on-github-codespace"},"Using the DevContainer.json on Github Codespace"),(0,o.kt)("p",null,"As a user, opening a workspace with all what we configured is done using a single click."),(0,o.kt)("p",null,"Go to ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman-desktop"},"https://github.com/containers/podman-desktop")," then click on the ",(0,o.kt)("inlineCode",{parentName:"p"},"< > Code")," dropdown and click on ",(0,o.kt)("inlineCode",{parentName:"p"},"Create codespace on main")," button."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Open Codespace",src:t(7486).Z,width:"1240",height:"617"})),(0,o.kt)("p",null,"Once you click on the button, the codespace is setting up:"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Preparing Codepace",src:t(6289).Z,width:"754",height:"587"})),(0,o.kt)("p",null,"After few minutes, as there is not yet ",(0,o.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/prebuilding-your-codespaces/about-github-codespaces-prebuilds"},"prebuilt codespaces"),", the codespace is opening."),(0,o.kt)("p",null,"The simple Browser displays the noVNC window:\n",(0,o.kt)("img",{alt:"Opening Codespace",src:t(8559).Z,width:"2051",height:"1066"})),(0,o.kt)("p",null,"Click on the connect button. Then on the terminal you can enter ",(0,o.kt)("inlineCode",{parentName:"p"},"podman run quay.io/podman/hello")," and the container is detected in Podman Desktop.\n",(0,o.kt)("img",{alt:"Testing Codespace",src:t(2972).Z,width:"2051",height:"1066"})),(0,o.kt)("p",null,"It's also possible using the port widget to get on ",(0,o.kt)("inlineCode",{parentName:"p"},"3000")," port by clicking on the world icon a preview of the website in another tab. Changing source code of the website will refresh the content of the window."),(0,o.kt)("p",null,"Depending on the usecase, it's also possible to open documentation in the preview browser."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Edit website Codespace",src:t(3517).Z,width:"2051",height:"1066"})),(0,o.kt)("h2",{id:"conclusion"},"Conclusion"),(0,o.kt)("p",null,"The DevContainer image for Podman Desktop is recent so it'll probably evolve over time by adding new capabilities but it allows you to easily build/run/experiment and ",(0,o.kt)("strong",{parentName:"p"},"contribute")," to the tool or the website."))}c.isMDXComponent=!0},7486:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-click-repository-22eb251ecc45a2b29952fe5983e16238.png"},3517:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-edit-website-d1f2a645f97209e453bc72cadafa0b54.png"},8559:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-open-novnc-ec3f30d836eb7af5750498a833d37184.png"},6289:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-preparing-codespace-3121417aa9d8947b8f5566bf39478961.png"},2972:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-testing-podman-desktop-3210aa766f273a52253d27cb4e7ef782.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7138],{5318:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>m});var a=t(7378);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},d=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),u=p(t),m=o,h=u["".concat(l,".").concat(m)]||u[m]||c[m]||r;return t?a.createElement(h,i(i({ref:n},d),{},{components:t})):a.createElement(h,i({ref:n},d))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var r=t.length,i=new Array(r);i[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:o,i[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var a=t(2685),o=(t(7378),t(5318));const r={title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",slug:"develop-using-devcontainer",authors:["benoitf"],tags:["podman-desktop","devcontainer","codespaces"],hide_table_of_contents:!1},i=void 0,s={permalink:"/blog/develop-using-devcontainer",source:"@site/blog/2022-11-17-develop-podman-using-codespaces.md",title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",date:"2022-11-17T00:00:00.000Z",formattedDate:"November 17, 2022",tags:[{label:"podman-desktop",permalink:"/blog/tags/podman-desktop"},{label:"devcontainer",permalink:"/blog/tags/devcontainer"},{label:"codespaces",permalink:"/blog/tags/codespaces"}],readingTime:6.985,hasTruncateMarker:!0,authors:[{name:"Florent Benoit",title:"Maintainer of Podman Desktop",url:"https://github.com/benoitf",imageURL:"https://github.com/benoitf.png",key:"benoitf"}],frontMatter:{title:"Build & run Podman Desktop in a DevContainer",description:"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.",slug:"develop-using-devcontainer",authors:["benoitf"],tags:["podman-desktop","devcontainer","codespaces"],hide_table_of_contents:!1},prevItem:{title:"Release Notes - Podman Desktop 0.10",permalink:"/blog/podman-desktop-release-0.10"}},l={authorsImageUrls:[void 0]},p=[{value:"Defining image of the container",id:"defining-image-of-the-container",level:2},{value:"Configure the DevContainer using devcontainer.json",id:"configure-the-devcontainer-using-devcontainerjson",level:2},{value:"Using the DevContainer.json on Github Codespace",id:"using-the-devcontainerjson-on-github-codespace",level:2},{value:"Conclusion",id:"conclusion",level:2}],d={toc:p};function c(e){let{components:n,...r}=e;return(0,o.kt)("wrapper",(0,a.Z)({},d,r,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"GitHub ",(0,o.kt)("a",{parentName:"p",href:"https://github.blog/changelog/2022-11-09-codespaces-for-free-and-pro-accounts/"},"announced last week")," that Codespaces is available for everyone and it includes free minutes."),(0,o.kt)("p",null,"Let see how we can use a ",(0,o.kt)("a",{parentName:"p",href:"https://containers.dev/"},"Development Container")," having all the tools to build and run Podman Desktop. The Development Container works locally using Visual Studio Code but in this blog post we will see how it works directly with a simple click from GitHub."),(0,o.kt)("p",null,"The challenges are to run a desktop tool (Podman Desktop) and running a container engine (Podman) inside this Development Container without using too many memory !"),(0,o.kt)("h2",{id:"defining-image-of-the-container"},"Defining image of the container"),(0,o.kt)("p",null,"The first thing is in the choice of the image for the container. It is possible to pick-up a default image and add some features but there is no existing feature for Podman at ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/devcontainers/features/tree/main/src"},"https://github.com/devcontainers/features/tree/main/src")," and most of the features are expecting to run on top of Debian/Ubuntu"),(0,o.kt)("p",null,"If you are not interested in how to setup the image, jump to the ",(0,o.kt)("a",{parentName:"p",href:"#configure-the-devcontainer-using-devcontainerjson"},"next section"),"."),(0,o.kt)("p",null,"Podman binaries are available quickly after the releases for Fedora. I decided then to use ",(0,o.kt)("inlineCode",{parentName:"p"},"Fedora 37")," as the base image."),(0,o.kt)("p",null,"Let start the Containerfile using:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"FROM quay.io/fedora/fedora:37\n")),(0,o.kt)("p",null,"Then I install Node.js 16 from official nodejs.org repository. It's easier to switch to the version that we need."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},'# install Node.js + yarn\nENV NODE_VERSION 16.18.1\nRUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" && \\\n tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 && \\\n rm "node-v$NODE_VERSION-linux-x64.tar.gz" && \\\n npm install -g yarn\n')),(0,o.kt)("p",null,"Now, all system dependencies used to run an Electron application needs to be installed."),(0,o.kt)("p",null,"Podman is also installed so we can run some containers inside this container."),(0,o.kt)("p",null,"And of course, we need to install VNC (I choose ",(0,o.kt)("a",{parentName:"p",href:"https://tigervnc.org/"},"tigervnc"),") with a light Window Manager (",(0,o.kt)("a",{parentName:"p",href:"http://fluxbox.org/"},"fluxbox"),")."),(0,o.kt)("p",null,"To connect to the display of the container, we need to expose VNC over HTML/websocket using ",(0,o.kt)("a",{parentName:"p",href:"https://novnc.com/"},"noVNC")),(0,o.kt)("p",null,"xterm is installed to start a terminal from the VNC side."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"RUN dnf -y update && \\\n yum -y reinstall shadow-utils && \\\n yum install -y git \\\n # dependencies for Podman Desktop\n nss \\\n atk \\\n at-spi2-atk \\\n cups-libs \\\n gtk3 \\\n # for remote Display\n fluxbox \\\n tigervnc-server \\\n xorg-x11-fonts-Type1 \\\n novnc \\\n supervisor \\\n xdpyinfo \\\n # for podman\n podman \\\n fuse-overlayfs --exclude container-selinux \\\n xterm && \\\n rm -rf /var/cache /var/log/dnf* /var/log/yum.*\n")),(0,o.kt)("p",null,"Supervisord setup the launch of the VNC server and the Window manager"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"COPY supervisord.conf /etc/supervisord.conf\n")),(0,o.kt)("p",null,"A custom theme for fluxbox:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"COPY fluxbox /usr/share/fluxbox/init\n")),(0,o.kt)("p",null,"Then we need a special configuration to allow to have Podman working inside the container"),(0,o.kt)("p",null,"We add the ",(0,o.kt)("inlineCode",{parentName:"p"},"podman-desktop")," user with correct range on subuid and subgid when running containers. I used the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration"},"tutorial"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"RUN useradd -u 1000 podman-desktop && echo podman-desktop:10000:5000 > /etc/subuid && echo podman-desktop:10000:5000 > /etc/subgid\n")),(0,o.kt)("p",null,"Then use some default configuration files"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"# initialize conf files\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman-desktop/.config/containers/containers.conf\n")),(0,o.kt)("p",null,"and make sure that all permissions are correct following the guide ",(0,o.kt)("a",{parentName:"p",href:"https://www.redhat.com/sysadmin/podman-inside-container"},"https://www.redhat.com/sysadmin/podman-inside-container")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"# set permissions\nRUN chown podman-desktop:podman-desktop -R /home/podman-desktop && chmod 644 /etc/containers/containers.conf && \\\n mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock && \\\n mkdir -p /run/user/1000 && chown podman-desktop:podman-desktop /run/user/1000\n")),(0,o.kt)("p",null,"plus define an empty user namespace."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},'ENV _CONTAINERS_USERNS_CONFIGURED=""\n')),(0,o.kt)("p",null,"Make sure Podman will create the socket in an expected directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"# socket path for podman\nENV XDG_RUNTIME_DIR=/run/user/1000\n")),(0,o.kt)("p",null,"OK ! we have a custom Containerfile providing all the tools to build and run Podman Desktop (using VNC for the display), run Podman and run Electron."),(0,o.kt)("p",null,"The current file is available at ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile"},"https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile")),(0,o.kt)("p",null,"Let's configure the DevContainer."),(0,o.kt)("h2",{id:"configure-the-devcontainer-using-devcontainerjson"},"Configure the DevContainer using devcontainer.json"),(0,o.kt)("p",null,"DevContainer definition is stored at ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer/devcontainer.json")," file."),(0,o.kt)("p",null,"We need to reuse the image of the previous step. For that let's use the build section of the ",(0,o.kt)("inlineCode",{parentName:"p"},"devcontainer.json")," file."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"build": {\n "dockerfile": "Containerfile"\n},\n')),(0,o.kt)("p",null,"In order to avoid to redo all the build steps each time we open a workspace using this dev container, we published the image to quay.io at ",(0,o.kt)("a",{parentName:"p",href:"https://quay.io/repository/podman-desktop/devcontainer-parent?tab=tags&tag=next"},"quay.io/podman-desktop/devcontainer-parent:next\n"),". This parent image is not changing much so it's better to use is as a parent one."),(0,o.kt)("p",null,"Inside ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," directory there is a ",(0,o.kt)("inlineCode",{parentName:"p"},".parent")," directory with everything related to the parent image."),(0,o.kt)("p",null,"And in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer/Containerfile")," file we reference this image"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-docker"},"FROM quay.io/podman-desktop/devcontainer-parent:next\n")),(0,o.kt)("p",null,"By default, we will be ",(0,o.kt)("inlineCode",{parentName:"p"},"root")," in the container and this is probably not what we expect. Let's change that."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"containerUser": "podman-desktop"\n')),(0,o.kt)("p",null,"Some Visual Studio Code extensions are nice to use and we can add them"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},' "extensions": ["svelte.svelte-vscode", "bradlc.vscode-tailwindcss"]\n')),(0,o.kt)("p",null,"Then here is the tricky part, how to run our container allowing to run again inside the container some containers with podman."),(0,o.kt)("p",null,"We specify the arguments to make it possible. It's possible to use ",(0,o.kt)("inlineCode",{parentName:"p"},"--privileged")," flag but I prefer to list the subset of permissions.\nUsing ",(0,o.kt)("inlineCode",{parentName:"p"},"--privileged")," we don't really know what are the privilege that are required while specifying all of them, people are aware of what is granted/denied."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"runArgs": [\n "--cap-add=sys_admin",\n "--security-opt",\n "seccomp=unconfined",\n "--device",\n "/dev/fuse",\n "--security-opt",\n "label=disable",\n "--security-opt",\n "apparmor=unconfined"\n ],\n')),(0,o.kt)("p",null,"Source code of Podman Desktop needs to be editable within the DevContainer so it needs to be mounted."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",\n"workspaceFolder": "/workspace",\n')),(0,o.kt)("p",null,"Then we need a command to build Podman Desktop."),(0,o.kt)("p",null,"For that, we use ",(0,o.kt)("inlineCode",{parentName:"p"},"onCreateCommand")," hook with a custom command"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"onCreateCommand": "${containerWorkspaceFolder}/.devcontainer/onCreateCommand.sh",\n')),(0,o.kt)("p",null,"and in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," folder the ",(0,o.kt)("inlineCode",{parentName:"p"},"onCreateCommand.sh")," script is the following"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"#!/bin/sh\nyarn\n\nMODE=production yarn run build && yarn run electron-builder build --linux --dir --config .electron-builder.config.cjs\n")),(0,o.kt)("p",null,"Two instructions:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"Fetch all Node.js dependencies."),(0,o.kt)("li",{parentName:"ol"},"build Podman Desktop in the ",(0,o.kt)("inlineCode",{parentName:"li"},"dist")," folder using ",(0,o.kt)("inlineCode",{parentName:"li"},"Linux")," as target Operating System.")),(0,o.kt)("p",null,"After the start of the container, how to launch Podman Desktop, the website and VNC, etc ?"),(0,o.kt)("p",null,"Just use ",(0,o.kt)("inlineCode",{parentName:"p"},"postStartCommand")," hook."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"postStartCommand": "${containerWorkspaceFolder}/.devcontainer/postStartCommand.sh",\n')),(0,o.kt)("p",null,"and in the ",(0,o.kt)("inlineCode",{parentName:"p"},".devcontainer")," folder the ",(0,o.kt)("inlineCode",{parentName:"p"},"postStartCommand.sh")," script is the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},'#!/bin/sh\n\n# Start all services\n/usr/bin/supervisord -c /etc/supervisord.conf &\n\n# wait X server to be ready or after 2mn exit\necho "Waiting for X server to be ready"\ntimeout 120 bash -c \'until xdpyinfo -display :0 &> /dev/null; do printf "."; sleep 1; done\'\n\n# launch podman desktop\necho "Launching Podman Desktop"\ncd dist/linux-unpacked/&& ./podman-desktop &\n\n# Launch the 9000 redirect after 20 seconds\nsleep 20\nwebsockify --web=/usr/share/novnc localhost:9000 localhost:5900 &\n\n# launch the website rendering\necho "Launching Website"\ncd website && yarn start\n')),(0,o.kt)("p",null,"It starts VNC and noVNC, start precompiled Podman Desktop and start the documentation rendering."),(0,o.kt)("p",null,"It is not launching the Watch mode/development mode of Podman Desktop as it requires a container having more than 8GB of memory."),(0,o.kt)("p",null,"Picking up a larger instace with for example 16GB, it's possible to use development mode."),(0,o.kt)("p",null,"Of course, to make VNC happy, we need to specify the ",(0,o.kt)("inlineCode",{parentName:"p"},"DISPLAY")," environment variable."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"remoteEnv": {\n "DISPLAY": ":0"\n}\n')),(0,o.kt)("p",null,"When the DevContainer is fully available, we want to have a way to quickly open the ",(0,o.kt)("inlineCode",{parentName:"p"},"Website rendering URL")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"noVNC")),(0,o.kt)("p",null,"Let's tweak the ",(0,o.kt)("inlineCode",{parentName:"p"},"devcontainer.json")," file by adding the ",(0,o.kt)("inlineCode",{parentName:"p"},"portsAttributes")," section"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"portsAttributes": {\n "9000": {\n "label": "vnc",\n "onAutoForward": "openPreview"\n },\n "3000": {\n "label": "website"\n }\n}\n')),(0,o.kt)("p",null,"After all post-creation steps, the ",(0,o.kt)("inlineCode",{parentName:"p"},"Preview")," browser inside the VS Code editor will open a window to VNC. And another port (",(0,o.kt)("inlineCode",{parentName:"p"},"3000"),") is flagged for the website."),(0,o.kt)("h2",{id:"using-the-devcontainerjson-on-github-codespace"},"Using the DevContainer.json on Github Codespace"),(0,o.kt)("p",null,"As a user, opening a workspace with all what we configured is done using a single click."),(0,o.kt)("p",null,"Go to ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/containers/podman-desktop"},"https://github.com/containers/podman-desktop")," then click on the ",(0,o.kt)("inlineCode",{parentName:"p"},"< > Code")," dropdown and click on ",(0,o.kt)("inlineCode",{parentName:"p"},"Create codespace on main")," button."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Open Codespace",src:t(7486).Z,width:"1240",height:"617"})),(0,o.kt)("p",null,"Once you click on the button, the codespace is setting up:"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Preparing Codepace",src:t(6289).Z,width:"754",height:"587"})),(0,o.kt)("p",null,"After few minutes, as there is not yet ",(0,o.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/prebuilding-your-codespaces/about-github-codespaces-prebuilds"},"prebuilt codespaces"),", the codespace is opening."),(0,o.kt)("p",null,"The simple Browser displays the noVNC window:\n",(0,o.kt)("img",{alt:"Opening Codespace",src:t(8559).Z,width:"2051",height:"1066"})),(0,o.kt)("p",null,"Click on the connect button. Then on the terminal you can enter ",(0,o.kt)("inlineCode",{parentName:"p"},"podman run quay.io/podman/hello")," and the container is detected in Podman Desktop.\n",(0,o.kt)("img",{alt:"Testing Codespace",src:t(2972).Z,width:"2051",height:"1066"})),(0,o.kt)("p",null,"It's also possible using the port widget to get on ",(0,o.kt)("inlineCode",{parentName:"p"},"3000")," port by clicking on the world icon a preview of the website in another tab. Changing source code of the website will refresh the content of the window."),(0,o.kt)("p",null,"Depending on the usecase, it's also possible to open documentation in the preview browser."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Edit website Codespace",src:t(3517).Z,width:"2051",height:"1066"})),(0,o.kt)("h2",{id:"conclusion"},"Conclusion"),(0,o.kt)("p",null,"The DevContainer image for Podman Desktop is recent so it'll probably evolve over time by adding new capabilities but it allows you to easily build/run/experiment and ",(0,o.kt)("strong",{parentName:"p"},"contribute")," to the tool or the website."))}c.isMDXComponent=!0},7486:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-click-repository-22eb251ecc45a2b29952fe5983e16238.png"},3517:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-edit-website-d1f2a645f97209e453bc72cadafa0b54.png"},8559:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-open-novnc-ec3f30d836eb7af5750498a833d37184.png"},6289:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-preparing-codespace-3121417aa9d8947b8f5566bf39478961.png"},2972:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/codespaces-testing-podman-desktop-3210aa766f273a52253d27cb4e7ef782.png"}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.a2d1b4be.js b/assets/js/b2f554cd.71472b0f.js similarity index 82% rename from assets/js/b2f554cd.a2d1b4be.js rename to assets/js/b2f554cd.71472b0f.js index d859c727cf6..8faa8782fa4 100644 --- a/assets/js/b2f554cd.a2d1b4be.js +++ b/assets/js/b2f554cd.71472b0f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1477],{4556:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"podman-desktop-release-0.10","metadata":{"permalink":"/blog/podman-desktop-release-0.10","source":"@site/blog/2022-12-01-release-0.10-blog.md","title":"Release Notes - Podman Desktop 0.10","description":"Podman Desktop 0.10 has been released! New Create Container Wizard, improved Kubernetes workflows, revamped registries configuration, and more!","date":"2022-12-01T00:00:00.000Z","formattedDate":"December 1, 2022","tags":[{"label":"podman-desktop","permalink":"/blog/tags/podman-desktop"},{"label":"release","permalink":"/blog/tags/release"},{"label":"kubernetes","permalink":"/blog/tags/kubernetes"}],"readingTime":4.09,"hasTruncateMarker":true,"authors":[{"name":"Dev Kumar","title":"Technical PMM Intern","url":"https://github.com/deekay2310","imageURL":"https://github.com/deekay2310.png","key":"deekay2310"}],"frontMatter":{"title":"Release Notes - Podman Desktop 0.10","description":"Podman Desktop 0.10 has been released! New Create Container Wizard, improved Kubernetes workflows, revamped registries configuration, and more!","slug":"podman-desktop-release-0.10","authors":["deekay2310"],"tags":["podman-desktop","release","kubernetes"],"hide_table_of_contents":false},"nextItem":{"title":"Build & run Podman Desktop in a DevContainer","permalink":"/blog/develop-using-devcontainer"}},"content":"This release note covers Podman Desktop 0.10 release changes.\\n\\n- **Containers Configuration**: Container creation wizzard allowing to define environment variables, networking and more configuration options.\\n- **Kubernetes Improvements**: Play Kubernetes YAML, custom Kubeconfig path support, reload of kube context.\\n- **Registries Configuration**: Revamped registries configuration UI.\\n- **Podman Version**: Podman 4.3.1 now included in Windows and Mac installers.\\n- **UX/UI Improvements**: Improved lists, better contrast, and more.\\n\\nPodman Desktop 0.10 is now available. [Click here to download it](/downloads)! \\n\\n\x3c!--truncate--\x3e\\n_________________\\n\\n## Release Details\\n\\n### New configuration wizzard to create containers ([#773](https://github.com/containers/podman-desktop/pull/773))\\n\\nUntil now, we could only specify port binding when building images to start containers. The create container wizzard now includes several options enabling configuring volumes, environment variables, restart policy and settings on networking and security. It is also possible to reuse an existing (and already configured) a network when creating containers.\\n\\n![new container creation wizard](img/podman-desktop-release-0.10/new_container_creation_wizard.gif)\\n\\n### Kubernetes Capabilities Improvements\\n\\n**Custom Kubeconfig file path ([#780](https://github.com/containers/podman-desktop/pull/780))** \\n\\nKubeconfig path location is now configurable from `Settings > Preferences > Kubernetes: Kubeconfig` and can be set to a custom path. By default, Podman Desktop use the path `$HOME/.kube/config` for the Kubeconfig file.\\n\\n![custom kubeconfig file path](img/podman-desktop-release-0.10/custom-kubeconfig.png)\\n\\n**Play Kubernetes YAML from the Pods list ([#739](https://github.com/containers/podman-desktop/pull/739))**\\n\\nPodman Desktop enables to play existing Kubernetes YAML files. This is now available from `Play Kubernetes YAML` button added to the Pods list, in addition to the Containers list. \\n\\n![play k8s yaml](img/podman-desktop-release-0.10/play_k8s_yaml.gif)\\n\\n**Kube context automatically reloaded when updated ([#813](https://github.com/containers/podman-desktop/pull/813))**\\n\\nAny change to the kube context will now be detected by Podman Desktop in its running state. The system tray, allowing to select which Kubernetes environment to work with, will now reload the kube context without restarting Podman Desktop.\\n\\n### Revamped Container Registries UI ([#446](https://github.com/containers/podman-desktop/issues/446))\\n\\nThe registries configuration UI has been revamped. Instead of using tiles for displaying the registries, now it uses a list where each registry can be added or edited directly in the list. The kebab menu provides options to edit or remove a registry from the list. \\n\\n![registries](img/podman-desktop-release-0.10/registries.png)\\n\\n### Update to Podman 4.3.1 ([#913](https://github.com/containers/podman-desktop/issues/913))\\n\\nPodman Desktop 0.10 is now embedding [Podman 4.3.1](https://github.com/containers/podman/releases/tag/v4.3.1) in Windows and macOS installers. \\n\\n### UI/UX Improvements\\n\\n**Improved lists UX ([#877](https://github.com/containers/podman-desktop/pull/877))**\\n\\nTo reduce the width used in the lists when displaying all the icons, main actions icons are now always displayed (before it was on hover) and the secondary actions are displayed in a kebab menu. For example Start/Stop and delete are primary actions while open the browser, inspect, generate kube yaml, etc. are secondary options.\\n\\n![kebab menu](img/podman-desktop-release-0.10/kebab-menu.png)\\n\\n**Delay appearance of text in navbar ([#767](https://github.com/containers/podman-desktop/pull/767))**\\n\\nWhen minimizing or expanding the navbar, the text was overlapping for a few second the page. Now it\'s displayed with a fading animation. \\n\\n**Selected state: better text color contrast ([#802](https://github.com/containers/podman-desktop/pull/802))**\\n\\nIn the `Images` page, on hover for both the image and the name column, the text contrast has been increased for better visibility: violet indicates that you have selected it.\\n\\n![text color when hover](img/podman-desktop-release-0.10/text-color.gif)\\n\\n**On Linux and Windows, the menu bar is now hidden by default ([#668](https://github.com/containers/podman-desktop/pull/668))**\\n\\nWith this change, the menu bar looks more integrated to the Operating System. The menu can appear if you hit the `Alt` key. Thanks to [Dylan M. Taylor](https://github.com/dylanmtaylor) for contributing to fix this.\\n\\n**Exit when clicking on the close icon of the dashboard on Linux ([#671](https://github.com/containers/podman-desktop/pull/671))**\\n\\nFor most users on Linux, there is no tray icon support. In this situation, when closed, Podman Desktop continues to run in background. [Dylan M. Taylor](https://github.com/dylanmtaylor) added a property to exit the app by default when clicking on the close icon. For people having tray icon support or with the desire of a different behavior, it is possible to disable it from the Settings.\\n\\n_________________\\n\\n## Other Notable Enhancements\\n\\n- Rename `Started` into `Age` in Containers list.([#878](https://github.com/containers/podman-desktop/pull/878))\\n- Added domain validation when adding a registry. ([#838](https://github.com/containers/podman-desktop/pull/838))\\n- Provided a consistent behavior with Podman CLI, `podman-machine-default` is now the default name when creating a Podman machine from Podman Desktop. ([#775](https://github.com/containers/podman-desktop/pull/775))\\n\\n_________________\\n\\n## Notable bug fixes\\n\\n- Fixed error handling when pulling images of Desktop Extensions. ([#782](https://github.com/containers/podman-desktop/pull/782))\\n- Fixed use of the full height of the screen when displaying log in the details of a container. ([#946](https://github.com/containers/podman-desktop/discussions/946))\\n- Fixed First start of Podman Desktop on flatpak was not seeing the podman engine ([#860](https://github.com/containers/podman-desktop/pull/860))\\n\\n## Community Thank You!\\n\\n\ud83c\udf89 We\u2019d like to say a big thank you to everyone who helped to make Podman Desktop 0.10 even better:\\n\\n- [Dylan M. Taylor](https://github.com/dylanmtaylor) in [#671](https://github.com/containers/podman-desktop/pull/671)\\n- [Fionn Kelleher](https://github.com/osslate) in [#713](https://github.com/containers/podman-desktop/pull/713)\\n- [Rostislav Svoboda](https://github.com/rsvoboda) in [#737](https://github.com/containers/podman-desktop/pull/737)\\n- [Denis Shemanaev](https://github.com/shemanaev) in [#783](https://github.com/containers/podman-desktop/pull/783)\\n- [Fabrice Flore-Th\xe9bault](https://github.com/themr0c) in [#856](https://github.com/containers/podman-desktop/pull/856)\\n- [Kevin](https://github.com/KevinAtSesam) in [#864](https://github.com/containers/podman-desktop/pull/864)\\n- [@sfrunza13](https://github.com/sfrunza13) in [#872](https://github.com/containers/podman-desktop/pull/872)\\n- [Anjan Nath](https://github.com/anjannath) in [#918](https://github.com/containers/podman-desktop/pull/918)\\n\\n## Final Notes\\n\\nThe complete list of issues fixed in this release is available [here](https://github.com/containers/podman-desktop/issues?q=is%3Aclosed+milestone%3A0.10.0).\\n\\nGet the latest release from the [Downloads](/downloads) section of the website and boost your development journey with Podman Desktop. Additionally, visit the [GitHub repository](https://github.com/containers/podman-desktop) and see how you can help us make Podman Desktop better."},{"id":"develop-using-devcontainer","metadata":{"permalink":"/blog/develop-using-devcontainer","source":"@site/blog/2022-11-17-develop-podman-using-codespaces.md","title":"Build & run Podman Desktop in a DevContainer","description":"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.","date":"2022-11-17T00:00:00.000Z","formattedDate":"November 17, 2022","tags":[{"label":"podman-desktop","permalink":"/blog/tags/podman-desktop"},{"label":"devcontainer","permalink":"/blog/tags/devcontainer"},{"label":"codespaces","permalink":"/blog/tags/codespaces"}],"readingTime":6.985,"hasTruncateMarker":true,"authors":[{"name":"Florent Benoit","title":"Maintainer of Podman Desktop","url":"https://github.com/benoitf","imageURL":"https://github.com/benoitf.png","key":"benoitf"}],"frontMatter":{"title":"Build & run Podman Desktop in a DevContainer","description":"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.","slug":"develop-using-devcontainer","authors":["benoitf"],"tags":["podman-desktop","devcontainer","codespaces"],"hide_table_of_contents":false},"prevItem":{"title":"Release Notes - Podman Desktop 0.10","permalink":"/blog/podman-desktop-release-0.10"}},"content":"GitHub [announced last week](https://github.blog/changelog/2022-11-09-codespaces-for-free-and-pro-accounts/) that Codespaces is available for everyone and it includes free minutes.\\n\\nLet see how we can use a [Development Container](https://containers.dev/) having all the tools to build and run Podman Desktop. The Development Container works locally using Visual Studio Code but in this blog post we will see how it works directly with a simple click from GitHub.\\n\\nThe challenges are to run a desktop tool (Podman Desktop) and running a container engine (Podman) inside this Development Container without using too many memory !\\n\\n\x3c!--truncate--\x3e\\n\\n## Defining image of the container\\n\\nThe first thing is in the choice of the image for the container. It is possible to pick-up a default image and add some features but there is no existing feature for Podman at https://github.com/devcontainers/features/tree/main/src and most of the features are expecting to run on top of Debian/Ubuntu\\n\\nIf you are not interested in how to setup the image, jump to the [next section](#configure-the-devcontainer-using-devcontainerjson).\\n\\nPodman binaries are available quickly after the releases for Fedora. I decided then to use `Fedora 37` as the base image.\\n\\nLet start the Containerfile using:\\n\\n```docker\\nFROM quay.io/fedora/fedora:37\\n```\\n\\nThen I install Node.js 16 from official nodejs.org repository. It\'s easier to switch to the version that we need.\\n\\n```docker\\n# install Node.js + yarn\\nENV NODE_VERSION 16.18.1\\nRUN curl -SLO \\"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz\\" && \\\\\\n tar -xzf \\"node-v$NODE_VERSION-linux-x64.tar.gz\\" -C /usr/local --strip-components=1 && \\\\\\n rm \\"node-v$NODE_VERSION-linux-x64.tar.gz\\" && \\\\\\n npm install -g yarn\\n```\\n\\nNow, all system dependencies used to run an Electron application needs to be installed.\\n\\nPodman is also installed so we can run some containers inside this container.\\n\\nAnd of course, we need to install VNC (I choose [tigervnc](https://tigervnc.org/)) with a light Window Manager ([fluxbox](http://fluxbox.org/)).\\n\\nTo connect to the display of the container, we need to expose VNC over HTML/websocket using [noVNC](https://novnc.com/)\\n\\nxterm is installed to start a terminal from the VNC side.\\n\\n```docker\\nRUN dnf -y update && \\\\\\n yum -y reinstall shadow-utils && \\\\\\n yum install -y git \\\\\\n # dependencies for Podman Desktop\\n nss \\\\\\n atk \\\\\\n at-spi2-atk \\\\\\n cups-libs \\\\\\n gtk3 \\\\\\n # for remote Display\\n fluxbox \\\\\\n tigervnc-server \\\\\\n xorg-x11-fonts-Type1 \\\\\\n novnc \\\\\\n supervisor \\\\\\n xdpyinfo \\\\\\n # for podman\\n podman \\\\\\n fuse-overlayfs --exclude container-selinux \\\\\\n xterm && \\\\\\n rm -rf /var/cache /var/log/dnf* /var/log/yum.*\\n```\\n\\nSupervisord setup the launch of the VNC server and the Window manager\\n\\n```docker\\nCOPY supervisord.conf /etc/supervisord.conf\\n```\\n\\nA custom theme for fluxbox:\\n```docker\\nCOPY fluxbox /usr/share/fluxbox/init\\n```\\n\\n\\nThen we need a special configuration to allow to have Podman working inside the container\\n\\nWe add the `podman-desktop` user with correct range on subuid and subgid when running containers. I used the [tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration).\\n\\n\\n```docker\\nRUN useradd -u 1000 podman-desktop && echo podman-desktop:10000:5000 > /etc/subuid && echo podman-desktop:10000:5000 > /etc/subgid\\n```\\n\\nThen use some default configuration files\\n```docker\\n# initialize conf files\\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf\\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman-desktop/.config/containers/containers.conf\\n```\\n\\nand make sure that all permissions are correct following the guide [https://www.redhat.com/sysadmin/podman-inside-container](https://www.redhat.com/sysadmin/podman-inside-container)\\n\\n```docker\\n# set permissions\\nRUN chown podman-desktop:podman-desktop -R /home/podman-desktop && chmod 644 /etc/containers/containers.conf && \\\\\\n mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock && \\\\\\n mkdir -p /run/user/1000 && chown podman-desktop:podman-desktop /run/user/1000\\n```\\n\\nplus define an empty user namespace.\\n\\n```docker\\nENV _CONTAINERS_USERNS_CONFIGURED=\\"\\"\\n```\\n\\nMake sure Podman will create the socket in an expected directory:\\n```\\n# socket path for podman\\nENV XDG_RUNTIME_DIR=/run/user/1000\\n```\\n\\nOK ! we have a custom Containerfile providing all the tools to build and run Podman Desktop (using VNC for the display), run Podman and run Electron.\\n\\nThe current file is available at https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile\\n\\n\\nLet\'s configure the DevContainer.\\n\\n\\n\\n## Configure the DevContainer using devcontainer.json\\n\\nDevContainer definition is stored at `.devcontainer/devcontainer.json` file.\\n\\nWe need to reuse the image of the previous step. For that let\'s use the build section of the `devcontainer.json` file.\\n\\n```json\\n\\"build\\": {\\n \\"dockerfile\\": \\"Containerfile\\"\\n},\\n```\\n\\nIn order to avoid to redo all the build steps each time we open a workspace using this dev container, we published the image to quay.io at [quay.io/podman-desktop/devcontainer-parent:next\\n](https://quay.io/repository/podman-desktop/devcontainer-parent?tab=tags&tag=next). This parent image is not changing much so it\'s better to use is as a parent one.\\n\\nInside `.devcontainer` directory there is a `.parent` directory with everything related to the parent image.\\n\\nAnd in the `.devcontainer/Containerfile` file we reference this image\\n\\n\\n```docker\\nFROM quay.io/podman-desktop/devcontainer-parent:next\\n```\\n\\nBy default, we will be `root` in the container and this is probably not what we expect. Let\'s change that.\\n\\n```json\\n\\"containerUser\\": \\"podman-desktop\\"\\n```\\n\\nSome Visual Studio Code extensions are nice to use and we can add them\\n```json\\n \\"extensions\\": [\\"svelte.svelte-vscode\\", \\"bradlc.vscode-tailwindcss\\"]\\n```\\n\\nThen here is the tricky part, how to run our container allowing to run again inside the container some containers with podman.\\n\\nWe specify the arguments to make it possible. It\'s possible to use `--privileged` flag but I prefer to list the subset of permissions.\\nUsing `--privileged` we don\'t really know what are the privilege that are required while specifying all of them, people are aware of what is granted/denied.\\n\\n```json\\n\\"runArgs\\": [\\n \\"--cap-add=sys_admin\\",\\n \\"--security-opt\\",\\n \\"seccomp=unconfined\\",\\n \\"--device\\",\\n \\"/dev/fuse\\",\\n \\"--security-opt\\",\\n \\"label=disable\\",\\n \\"--security-opt\\",\\n \\"apparmor=unconfined\\"\\n ],\\n```\\n\\nSource code of Podman Desktop needs to be editable within the DevContainer so it needs to be mounted.\\n\\n```json\\n\\"workspaceMount\\": \\"source=${localWorkspaceFolder},target=/workspace,type=bind\\",\\n\\"workspaceFolder\\": \\"/workspace\\",\\n```\\n\\nThen we need a command to build Podman Desktop.\\n\\nFor that, we use `onCreateCommand` hook with a custom command\\n\\n```json\\n\\"onCreateCommand\\": \\"${containerWorkspaceFolder}/.devcontainer/onCreateCommand.sh\\",\\n```\\n\\nand in the `.devcontainer` folder the `onCreateCommand.sh` script is the following\\n\\n```shell\\n#!/bin/sh\\nyarn\\n\\nMODE=production yarn run build && yarn run electron-builder build --linux --dir --config .electron-builder.config.js\\n```\\n\\nTwo instructions:\\n1. Fetch all Node.js dependencies.\\n2. build Podman Desktop in the `dist` folder using `Linux` as target Operating System.\\n\\nAfter the start of the container, how to launch Podman Desktop, the website and VNC, etc ?\\n\\nJust use `postStartCommand` hook.\\n\\n```json\\n\\"postStartCommand\\": \\"${containerWorkspaceFolder}/.devcontainer/postStartCommand.sh\\",\\n```\\n\\nand in the `.devcontainer` folder the `postStartCommand.sh` script is the following:\\n\\n```shell\\n#!/bin/sh\\n\\n# Start all services\\n/usr/bin/supervisord -c /etc/supervisord.conf &\\n\\n# wait X server to be ready or after 2mn exit\\necho \\"Waiting for X server to be ready\\"\\ntimeout 120 bash -c \'until xdpyinfo -display :0 &> /dev/null; do printf \\".\\"; sleep 1; done\'\\n\\n# launch podman desktop\\necho \\"Launching Podman Desktop\\"\\ncd dist/linux-unpacked/&& ./podman-desktop &\\n\\n# Launch the 9000 redirect after 20 seconds\\nsleep 20\\nwebsockify --web=/usr/share/novnc localhost:9000 localhost:5900 &\\n\\n# launch the website rendering\\necho \\"Launching Website\\"\\ncd website && yarn start\\n```\\n\\nIt starts VNC and noVNC, start precompiled Podman Desktop and start the documentation rendering.\\n\\nIt is not launching the Watch mode/development mode of Podman Desktop as it requires a container having more than 8GB of memory.\\n\\nPicking up a larger instace with for example 16GB, it\'s possible to use development mode.\\n\\nOf course, to make VNC happy, we need to specify the `DISPLAY` environment variable.\\n\\n```json\\n\\"remoteEnv\\": {\\n \\"DISPLAY\\": \\":0\\"\\n}\\n```\\n\\nWhen the DevContainer is fully available, we want to have a way to quickly open the `Website rendering URL` and `noVNC`\\n\\nLet\'s tweak the `devcontainer.json` file by adding the `portsAttributes` section\\n\\n```json\\n\\"portsAttributes\\": {\\n \\"9000\\": {\\n \\"label\\": \\"vnc\\",\\n \\"onAutoForward\\": \\"openPreview\\"\\n },\\n \\"3000\\": {\\n \\"label\\": \\"website\\"\\n }\\n}\\n```\\n\\nAfter all post-creation steps, the `Preview` browser inside the VS Code editor will open a window to VNC. And another port (`3000`) is flagged for the website.\\n\\n\\n## Using the DevContainer.json on Github Codespace\\n\\nAs a user, opening a workspace with all what we configured is done using a single click.\\n\\nGo to https://github.com/containers/podman-desktop then click on the `< > Code` dropdown and click on `Create codespace on main` button.\\n\\n![Open Codespace](img/develop-podman-using-codespaces/codespaces-click-repository.png)\\n\\nOnce you click on the button, the codespace is setting up:\\n\\n![Preparing Codepace](img/develop-podman-using-codespaces/codespaces-preparing-codespace.png)\\n\\nAfter few minutes, as there is not yet [prebuilt codespaces](https://docs.github.com/en/codespaces/prebuilding-your-codespaces/about-github-codespaces-prebuilds), the codespace is opening.\\n\\nThe simple Browser displays the noVNC window:\\n![Opening Codespace](img/develop-podman-using-codespaces/codespaces-open-novnc.png)\\n\\nClick on the connect button. Then on the terminal you can enter `podman run quay.io/podman/hello` and the container is detected in Podman Desktop.\\n![Testing Codespace](img/develop-podman-using-codespaces/codespaces-testing-podman-desktop.png)\\n\\nIt\'s also possible using the port widget to get on `3000` port by clicking on the world icon a preview of the website in another tab. Changing source code of the website will refresh the content of the window.\\n\\nDepending on the usecase, it\'s also possible to open documentation in the preview browser.\\n\\n![Edit website Codespace](img/develop-podman-using-codespaces/codespaces-edit-website.png)\\n\\n## Conclusion\\n\\nThe DevContainer image for Podman Desktop is recent so it\'ll probably evolve over time by adding new capabilities but it allows you to easily build/run/experiment and **contribute** to the tool or the website."}]}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1477],{4556:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"podman-desktop-release-0.10","metadata":{"permalink":"/blog/podman-desktop-release-0.10","source":"@site/blog/2022-12-01-release-0.10-blog.md","title":"Release Notes - Podman Desktop 0.10","description":"Podman Desktop 0.10 has been released! New Create Container Wizard, improved Kubernetes workflows, revamped registries configuration, and more!","date":"2022-12-01T00:00:00.000Z","formattedDate":"December 1, 2022","tags":[{"label":"podman-desktop","permalink":"/blog/tags/podman-desktop"},{"label":"release","permalink":"/blog/tags/release"},{"label":"kubernetes","permalink":"/blog/tags/kubernetes"}],"readingTime":4.09,"hasTruncateMarker":true,"authors":[{"name":"Dev Kumar","title":"Technical PMM Intern","url":"https://github.com/deekay2310","imageURL":"https://github.com/deekay2310.png","key":"deekay2310"}],"frontMatter":{"title":"Release Notes - Podman Desktop 0.10","description":"Podman Desktop 0.10 has been released! New Create Container Wizard, improved Kubernetes workflows, revamped registries configuration, and more!","slug":"podman-desktop-release-0.10","authors":["deekay2310"],"tags":["podman-desktop","release","kubernetes"],"hide_table_of_contents":false},"nextItem":{"title":"Build & run Podman Desktop in a DevContainer","permalink":"/blog/develop-using-devcontainer"}},"content":"This release note covers Podman Desktop 0.10 release changes.\\n\\n- **Containers Configuration**: Container creation wizzard allowing to define environment variables, networking and more configuration options.\\n- **Kubernetes Improvements**: Play Kubernetes YAML, custom Kubeconfig path support, reload of kube context.\\n- **Registries Configuration**: Revamped registries configuration UI.\\n- **Podman Version**: Podman 4.3.1 now included in Windows and Mac installers.\\n- **UX/UI Improvements**: Improved lists, better contrast, and more.\\n\\nPodman Desktop 0.10 is now available. [Click here to download it](/downloads)! \\n\\n\x3c!--truncate--\x3e\\n_________________\\n\\n## Release Details\\n\\n### New configuration wizzard to create containers ([#773](https://github.com/containers/podman-desktop/pull/773))\\n\\nUntil now, we could only specify port binding when building images to start containers. The create container wizzard now includes several options enabling configuring volumes, environment variables, restart policy and settings on networking and security. It is also possible to reuse an existing (and already configured) a network when creating containers.\\n\\n![new container creation wizard](img/podman-desktop-release-0.10/new_container_creation_wizard.gif)\\n\\n### Kubernetes Capabilities Improvements\\n\\n**Custom Kubeconfig file path ([#780](https://github.com/containers/podman-desktop/pull/780))** \\n\\nKubeconfig path location is now configurable from `Settings > Preferences > Kubernetes: Kubeconfig` and can be set to a custom path. By default, Podman Desktop use the path `$HOME/.kube/config` for the Kubeconfig file.\\n\\n![custom kubeconfig file path](img/podman-desktop-release-0.10/custom-kubeconfig.png)\\n\\n**Play Kubernetes YAML from the Pods list ([#739](https://github.com/containers/podman-desktop/pull/739))**\\n\\nPodman Desktop enables to play existing Kubernetes YAML files. This is now available from `Play Kubernetes YAML` button added to the Pods list, in addition to the Containers list. \\n\\n![play k8s yaml](img/podman-desktop-release-0.10/play_k8s_yaml.gif)\\n\\n**Kube context automatically reloaded when updated ([#813](https://github.com/containers/podman-desktop/pull/813))**\\n\\nAny change to the kube context will now be detected by Podman Desktop in its running state. The system tray, allowing to select which Kubernetes environment to work with, will now reload the kube context without restarting Podman Desktop.\\n\\n### Revamped Container Registries UI ([#446](https://github.com/containers/podman-desktop/issues/446))\\n\\nThe registries configuration UI has been revamped. Instead of using tiles for displaying the registries, now it uses a list where each registry can be added or edited directly in the list. The kebab menu provides options to edit or remove a registry from the list. \\n\\n![registries](img/podman-desktop-release-0.10/registries.png)\\n\\n### Update to Podman 4.3.1 ([#913](https://github.com/containers/podman-desktop/issues/913))\\n\\nPodman Desktop 0.10 is now embedding [Podman 4.3.1](https://github.com/containers/podman/releases/tag/v4.3.1) in Windows and macOS installers. \\n\\n### UI/UX Improvements\\n\\n**Improved lists UX ([#877](https://github.com/containers/podman-desktop/pull/877))**\\n\\nTo reduce the width used in the lists when displaying all the icons, main actions icons are now always displayed (before it was on hover) and the secondary actions are displayed in a kebab menu. For example Start/Stop and delete are primary actions while open the browser, inspect, generate kube yaml, etc. are secondary options.\\n\\n![kebab menu](img/podman-desktop-release-0.10/kebab-menu.png)\\n\\n**Delay appearance of text in navbar ([#767](https://github.com/containers/podman-desktop/pull/767))**\\n\\nWhen minimizing or expanding the navbar, the text was overlapping for a few second the page. Now it\'s displayed with a fading animation. \\n\\n**Selected state: better text color contrast ([#802](https://github.com/containers/podman-desktop/pull/802))**\\n\\nIn the `Images` page, on hover for both the image and the name column, the text contrast has been increased for better visibility: violet indicates that you have selected it.\\n\\n![text color when hover](img/podman-desktop-release-0.10/text-color.gif)\\n\\n**On Linux and Windows, the menu bar is now hidden by default ([#668](https://github.com/containers/podman-desktop/pull/668))**\\n\\nWith this change, the menu bar looks more integrated to the Operating System. The menu can appear if you hit the `Alt` key. Thanks to [Dylan M. Taylor](https://github.com/dylanmtaylor) for contributing to fix this.\\n\\n**Exit when clicking on the close icon of the dashboard on Linux ([#671](https://github.com/containers/podman-desktop/pull/671))**\\n\\nFor most users on Linux, there is no tray icon support. In this situation, when closed, Podman Desktop continues to run in background. [Dylan M. Taylor](https://github.com/dylanmtaylor) added a property to exit the app by default when clicking on the close icon. For people having tray icon support or with the desire of a different behavior, it is possible to disable it from the Settings.\\n\\n_________________\\n\\n## Other Notable Enhancements\\n\\n- Rename `Started` into `Age` in Containers list.([#878](https://github.com/containers/podman-desktop/pull/878))\\n- Added domain validation when adding a registry. ([#838](https://github.com/containers/podman-desktop/pull/838))\\n- Provided a consistent behavior with Podman CLI, `podman-machine-default` is now the default name when creating a Podman machine from Podman Desktop. ([#775](https://github.com/containers/podman-desktop/pull/775))\\n\\n_________________\\n\\n## Notable bug fixes\\n\\n- Fixed error handling when pulling images of Desktop Extensions. ([#782](https://github.com/containers/podman-desktop/pull/782))\\n- Fixed use of the full height of the screen when displaying log in the details of a container. ([#946](https://github.com/containers/podman-desktop/discussions/946))\\n- Fixed First start of Podman Desktop on flatpak was not seeing the podman engine ([#860](https://github.com/containers/podman-desktop/pull/860))\\n\\n## Community Thank You!\\n\\n\ud83c\udf89 We\u2019d like to say a big thank you to everyone who helped to make Podman Desktop 0.10 even better:\\n\\n- [Dylan M. Taylor](https://github.com/dylanmtaylor) in [#671](https://github.com/containers/podman-desktop/pull/671)\\n- [Fionn Kelleher](https://github.com/osslate) in [#713](https://github.com/containers/podman-desktop/pull/713)\\n- [Rostislav Svoboda](https://github.com/rsvoboda) in [#737](https://github.com/containers/podman-desktop/pull/737)\\n- [Denis Shemanaev](https://github.com/shemanaev) in [#783](https://github.com/containers/podman-desktop/pull/783)\\n- [Fabrice Flore-Th\xe9bault](https://github.com/themr0c) in [#856](https://github.com/containers/podman-desktop/pull/856)\\n- [Kevin](https://github.com/KevinAtSesam) in [#864](https://github.com/containers/podman-desktop/pull/864)\\n- [@sfrunza13](https://github.com/sfrunza13) in [#872](https://github.com/containers/podman-desktop/pull/872)\\n- [Anjan Nath](https://github.com/anjannath) in [#918](https://github.com/containers/podman-desktop/pull/918)\\n\\n## Final Notes\\n\\nThe complete list of issues fixed in this release is available [here](https://github.com/containers/podman-desktop/issues?q=is%3Aclosed+milestone%3A0.10.0).\\n\\nGet the latest release from the [Downloads](/downloads) section of the website and boost your development journey with Podman Desktop. Additionally, visit the [GitHub repository](https://github.com/containers/podman-desktop) and see how you can help us make Podman Desktop better."},{"id":"develop-using-devcontainer","metadata":{"permalink":"/blog/develop-using-devcontainer","source":"@site/blog/2022-11-17-develop-podman-using-codespaces.md","title":"Build & run Podman Desktop in a DevContainer","description":"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.","date":"2022-11-17T00:00:00.000Z","formattedDate":"November 17, 2022","tags":[{"label":"podman-desktop","permalink":"/blog/tags/podman-desktop"},{"label":"devcontainer","permalink":"/blog/tags/devcontainer"},{"label":"codespaces","permalink":"/blog/tags/codespaces"}],"readingTime":6.985,"hasTruncateMarker":true,"authors":[{"name":"Florent Benoit","title":"Maintainer of Podman Desktop","url":"https://github.com/benoitf","imageURL":"https://github.com/benoitf.png","key":"benoitf"}],"frontMatter":{"title":"Build & run Podman Desktop in a DevContainer","description":"Develop Podman Desktop using a DevContainer locally or using GitHub Codespaces.","slug":"develop-using-devcontainer","authors":["benoitf"],"tags":["podman-desktop","devcontainer","codespaces"],"hide_table_of_contents":false},"prevItem":{"title":"Release Notes - Podman Desktop 0.10","permalink":"/blog/podman-desktop-release-0.10"}},"content":"GitHub [announced last week](https://github.blog/changelog/2022-11-09-codespaces-for-free-and-pro-accounts/) that Codespaces is available for everyone and it includes free minutes.\\n\\nLet see how we can use a [Development Container](https://containers.dev/) having all the tools to build and run Podman Desktop. The Development Container works locally using Visual Studio Code but in this blog post we will see how it works directly with a simple click from GitHub.\\n\\nThe challenges are to run a desktop tool (Podman Desktop) and running a container engine (Podman) inside this Development Container without using too many memory !\\n\\n\x3c!--truncate--\x3e\\n\\n## Defining image of the container\\n\\nThe first thing is in the choice of the image for the container. It is possible to pick-up a default image and add some features but there is no existing feature for Podman at https://github.com/devcontainers/features/tree/main/src and most of the features are expecting to run on top of Debian/Ubuntu\\n\\nIf you are not interested in how to setup the image, jump to the [next section](#configure-the-devcontainer-using-devcontainerjson).\\n\\nPodman binaries are available quickly after the releases for Fedora. I decided then to use `Fedora 37` as the base image.\\n\\nLet start the Containerfile using:\\n\\n```docker\\nFROM quay.io/fedora/fedora:37\\n```\\n\\nThen I install Node.js 16 from official nodejs.org repository. It\'s easier to switch to the version that we need.\\n\\n```docker\\n# install Node.js + yarn\\nENV NODE_VERSION 16.18.1\\nRUN curl -SLO \\"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz\\" && \\\\\\n tar -xzf \\"node-v$NODE_VERSION-linux-x64.tar.gz\\" -C /usr/local --strip-components=1 && \\\\\\n rm \\"node-v$NODE_VERSION-linux-x64.tar.gz\\" && \\\\\\n npm install -g yarn\\n```\\n\\nNow, all system dependencies used to run an Electron application needs to be installed.\\n\\nPodman is also installed so we can run some containers inside this container.\\n\\nAnd of course, we need to install VNC (I choose [tigervnc](https://tigervnc.org/)) with a light Window Manager ([fluxbox](http://fluxbox.org/)).\\n\\nTo connect to the display of the container, we need to expose VNC over HTML/websocket using [noVNC](https://novnc.com/)\\n\\nxterm is installed to start a terminal from the VNC side.\\n\\n```docker\\nRUN dnf -y update && \\\\\\n yum -y reinstall shadow-utils && \\\\\\n yum install -y git \\\\\\n # dependencies for Podman Desktop\\n nss \\\\\\n atk \\\\\\n at-spi2-atk \\\\\\n cups-libs \\\\\\n gtk3 \\\\\\n # for remote Display\\n fluxbox \\\\\\n tigervnc-server \\\\\\n xorg-x11-fonts-Type1 \\\\\\n novnc \\\\\\n supervisor \\\\\\n xdpyinfo \\\\\\n # for podman\\n podman \\\\\\n fuse-overlayfs --exclude container-selinux \\\\\\n xterm && \\\\\\n rm -rf /var/cache /var/log/dnf* /var/log/yum.*\\n```\\n\\nSupervisord setup the launch of the VNC server and the Window manager\\n\\n```docker\\nCOPY supervisord.conf /etc/supervisord.conf\\n```\\n\\nA custom theme for fluxbox:\\n```docker\\nCOPY fluxbox /usr/share/fluxbox/init\\n```\\n\\n\\nThen we need a special configuration to allow to have Podman working inside the container\\n\\nWe add the `podman-desktop` user with correct range on subuid and subgid when running containers. I used the [tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration).\\n\\n\\n```docker\\nRUN useradd -u 1000 podman-desktop && echo podman-desktop:10000:5000 > /etc/subuid && echo podman-desktop:10000:5000 > /etc/subgid\\n```\\n\\nThen use some default configuration files\\n```docker\\n# initialize conf files\\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf\\nADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman-desktop/.config/containers/containers.conf\\n```\\n\\nand make sure that all permissions are correct following the guide [https://www.redhat.com/sysadmin/podman-inside-container](https://www.redhat.com/sysadmin/podman-inside-container)\\n\\n```docker\\n# set permissions\\nRUN chown podman-desktop:podman-desktop -R /home/podman-desktop && chmod 644 /etc/containers/containers.conf && \\\\\\n mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock && \\\\\\n mkdir -p /run/user/1000 && chown podman-desktop:podman-desktop /run/user/1000\\n```\\n\\nplus define an empty user namespace.\\n\\n```docker\\nENV _CONTAINERS_USERNS_CONFIGURED=\\"\\"\\n```\\n\\nMake sure Podman will create the socket in an expected directory:\\n```\\n# socket path for podman\\nENV XDG_RUNTIME_DIR=/run/user/1000\\n```\\n\\nOK ! we have a custom Containerfile providing all the tools to build and run Podman Desktop (using VNC for the display), run Podman and run Electron.\\n\\nThe current file is available at https://github.com/containers/podman-desktop/blob/main/.devcontainer/.parent/Containerfile\\n\\n\\nLet\'s configure the DevContainer.\\n\\n\\n\\n## Configure the DevContainer using devcontainer.json\\n\\nDevContainer definition is stored at `.devcontainer/devcontainer.json` file.\\n\\nWe need to reuse the image of the previous step. For that let\'s use the build section of the `devcontainer.json` file.\\n\\n```json\\n\\"build\\": {\\n \\"dockerfile\\": \\"Containerfile\\"\\n},\\n```\\n\\nIn order to avoid to redo all the build steps each time we open a workspace using this dev container, we published the image to quay.io at [quay.io/podman-desktop/devcontainer-parent:next\\n](https://quay.io/repository/podman-desktop/devcontainer-parent?tab=tags&tag=next). This parent image is not changing much so it\'s better to use is as a parent one.\\n\\nInside `.devcontainer` directory there is a `.parent` directory with everything related to the parent image.\\n\\nAnd in the `.devcontainer/Containerfile` file we reference this image\\n\\n\\n```docker\\nFROM quay.io/podman-desktop/devcontainer-parent:next\\n```\\n\\nBy default, we will be `root` in the container and this is probably not what we expect. Let\'s change that.\\n\\n```json\\n\\"containerUser\\": \\"podman-desktop\\"\\n```\\n\\nSome Visual Studio Code extensions are nice to use and we can add them\\n```json\\n \\"extensions\\": [\\"svelte.svelte-vscode\\", \\"bradlc.vscode-tailwindcss\\"]\\n```\\n\\nThen here is the tricky part, how to run our container allowing to run again inside the container some containers with podman.\\n\\nWe specify the arguments to make it possible. It\'s possible to use `--privileged` flag but I prefer to list the subset of permissions.\\nUsing `--privileged` we don\'t really know what are the privilege that are required while specifying all of them, people are aware of what is granted/denied.\\n\\n```json\\n\\"runArgs\\": [\\n \\"--cap-add=sys_admin\\",\\n \\"--security-opt\\",\\n \\"seccomp=unconfined\\",\\n \\"--device\\",\\n \\"/dev/fuse\\",\\n \\"--security-opt\\",\\n \\"label=disable\\",\\n \\"--security-opt\\",\\n \\"apparmor=unconfined\\"\\n ],\\n```\\n\\nSource code of Podman Desktop needs to be editable within the DevContainer so it needs to be mounted.\\n\\n```json\\n\\"workspaceMount\\": \\"source=${localWorkspaceFolder},target=/workspace,type=bind\\",\\n\\"workspaceFolder\\": \\"/workspace\\",\\n```\\n\\nThen we need a command to build Podman Desktop.\\n\\nFor that, we use `onCreateCommand` hook with a custom command\\n\\n```json\\n\\"onCreateCommand\\": \\"${containerWorkspaceFolder}/.devcontainer/onCreateCommand.sh\\",\\n```\\n\\nand in the `.devcontainer` folder the `onCreateCommand.sh` script is the following\\n\\n```shell\\n#!/bin/sh\\nyarn\\n\\nMODE=production yarn run build && yarn run electron-builder build --linux --dir --config .electron-builder.config.cjs\\n```\\n\\nTwo instructions:\\n1. Fetch all Node.js dependencies.\\n2. build Podman Desktop in the `dist` folder using `Linux` as target Operating System.\\n\\nAfter the start of the container, how to launch Podman Desktop, the website and VNC, etc ?\\n\\nJust use `postStartCommand` hook.\\n\\n```json\\n\\"postStartCommand\\": \\"${containerWorkspaceFolder}/.devcontainer/postStartCommand.sh\\",\\n```\\n\\nand in the `.devcontainer` folder the `postStartCommand.sh` script is the following:\\n\\n```shell\\n#!/bin/sh\\n\\n# Start all services\\n/usr/bin/supervisord -c /etc/supervisord.conf &\\n\\n# wait X server to be ready or after 2mn exit\\necho \\"Waiting for X server to be ready\\"\\ntimeout 120 bash -c \'until xdpyinfo -display :0 &> /dev/null; do printf \\".\\"; sleep 1; done\'\\n\\n# launch podman desktop\\necho \\"Launching Podman Desktop\\"\\ncd dist/linux-unpacked/&& ./podman-desktop &\\n\\n# Launch the 9000 redirect after 20 seconds\\nsleep 20\\nwebsockify --web=/usr/share/novnc localhost:9000 localhost:5900 &\\n\\n# launch the website rendering\\necho \\"Launching Website\\"\\ncd website && yarn start\\n```\\n\\nIt starts VNC and noVNC, start precompiled Podman Desktop and start the documentation rendering.\\n\\nIt is not launching the Watch mode/development mode of Podman Desktop as it requires a container having more than 8GB of memory.\\n\\nPicking up a larger instace with for example 16GB, it\'s possible to use development mode.\\n\\nOf course, to make VNC happy, we need to specify the `DISPLAY` environment variable.\\n\\n```json\\n\\"remoteEnv\\": {\\n \\"DISPLAY\\": \\":0\\"\\n}\\n```\\n\\nWhen the DevContainer is fully available, we want to have a way to quickly open the `Website rendering URL` and `noVNC`\\n\\nLet\'s tweak the `devcontainer.json` file by adding the `portsAttributes` section\\n\\n```json\\n\\"portsAttributes\\": {\\n \\"9000\\": {\\n \\"label\\": \\"vnc\\",\\n \\"onAutoForward\\": \\"openPreview\\"\\n },\\n \\"3000\\": {\\n \\"label\\": \\"website\\"\\n }\\n}\\n```\\n\\nAfter all post-creation steps, the `Preview` browser inside the VS Code editor will open a window to VNC. And another port (`3000`) is flagged for the website.\\n\\n\\n## Using the DevContainer.json on Github Codespace\\n\\nAs a user, opening a workspace with all what we configured is done using a single click.\\n\\nGo to https://github.com/containers/podman-desktop then click on the `< > Code` dropdown and click on `Create codespace on main` button.\\n\\n![Open Codespace](img/develop-podman-using-codespaces/codespaces-click-repository.png)\\n\\nOnce you click on the button, the codespace is setting up:\\n\\n![Preparing Codepace](img/develop-podman-using-codespaces/codespaces-preparing-codespace.png)\\n\\nAfter few minutes, as there is not yet [prebuilt codespaces](https://docs.github.com/en/codespaces/prebuilding-your-codespaces/about-github-codespaces-prebuilds), the codespace is opening.\\n\\nThe simple Browser displays the noVNC window:\\n![Opening Codespace](img/develop-podman-using-codespaces/codespaces-open-novnc.png)\\n\\nClick on the connect button. Then on the terminal you can enter `podman run quay.io/podman/hello` and the container is detected in Podman Desktop.\\n![Testing Codespace](img/develop-podman-using-codespaces/codespaces-testing-podman-desktop.png)\\n\\nIt\'s also possible using the port widget to get on `3000` port by clicking on the world icon a preview of the website in another tab. Changing source code of the website will refresh the content of the window.\\n\\nDepending on the usecase, it\'s also possible to open documentation in the preview browser.\\n\\n![Edit website Codespace](img/develop-podman-using-codespaces/codespaces-edit-website.png)\\n\\n## Conclusion\\n\\nThe DevContainer image for Podman Desktop is recent so it\'ll probably evolve over time by adding new capabilities but it allows you to easily build/run/experiment and **contribute** to the tool or the website."}]}')}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.f2735a76.js b/assets/js/runtime~main.03da001e.js similarity index 97% rename from assets/js/runtime~main.f2735a76.js rename to assets/js/runtime~main.03da001e.js index e8037f5ab4c..b1c5ca6d351 100644 --- a/assets/js/runtime~main.f2735a76.js +++ b/assets/js/runtime~main.03da001e.js @@ -1 +1 @@ -(()=>{"use strict";var e,c,a,t,r,d={},f={};function b(e){var c=f[e];if(void 0!==c)return c.exports;var a=f[e]={exports:{}};return d[e].call(a.exports,a,a.exports,b),a.exports}b.m=d,e=[],b.O=(c,a,t,r)=>{if(!a){var d=1/0;for(i=0;i=r)&&Object.keys(b.O).every((e=>b.O[e](a[o])))?a.splice(o--,1):(f=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[a,t,r]},b.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return b.d(c,{a:c}),c},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,b.t=function(e,t){if(1&t&&(e=this(e)),8&t)return e;if("object"==typeof e&&e){if(4&t&&e.__esModule)return e;if(16&t&&"function"==typeof e.then)return e}var r=Object.create(null);b.r(r);var d={};c=c||[null,a({}),a([]),a(a)];for(var f=2&t&&e;"object"==typeof f&&!~c.indexOf(f);f=a(f))Object.getOwnPropertyNames(f).forEach((c=>d[c]=()=>e[c]));return d.default=()=>e,b.d(r,d),r},b.d=(e,c)=>{for(var a in c)b.o(c,a)&&!b.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:c[a]})},b.f={},b.e=e=>Promise.all(Object.keys(b.f).reduce(((c,a)=>(b.f[a](e,c),c)),[])),b.u=e=>"assets/js/"+({53:"935f2afb",114:"e665718d",182:"c276ecb2",205:"83d480e9",397:"6194ac84",533:"b2b675dd",1241:"631e3189",1441:"382c5d2b",1477:"b2f554cd",1713:"a7023ddc",1724:"5087625a",2178:"ba322490",2217:"d7fbbe43",2535:"814f3328",3010:"56c3a9b2",3089:"a6aa9e1f",3130:"ac371aaa",3237:"1df93b7f",3259:"03ccf92d",3505:"72486833",3608:"9e4087bc",3636:"8b4dd820",3751:"3720c009",4013:"01a85c17",4121:"55960ee5",4207:"beebaad6",5068:"d83d689a",5248:"6101b3fc",5625:"657ac0bc",6049:"f213dd13",6103:"ccc49370",6181:"4e8ec325",6778:"cc591f25",7138:"38a042e4",7149:"822c343e",7251:"ba5b9f11",7438:"9c021584",7505:"8894e90f",7536:"f6e0e63c",7813:"933a69d3",7847:"43b416ef",7918:"17896441",7920:"1a4e3797",8262:"059d1c6a",8610:"6875c492",8860:"0d040286",9360:"9d9f8394",9372:"07f59c2a",9387:"b0f1c099",9514:"1be78505",9671:"0e384e19",9924:"df203c0f"}[e]||e)+"."+{53:"f55b66bc",114:"45b00829",182:"90a09a09",205:"915fdb35",397:"32fdc436",533:"fb35fe43",1241:"51c5a947",1441:"11ebaefe",1477:"a2d1b4be",1713:"e7d703ab",1724:"0bb1a1ff",1769:"f0bfbb81",1947:"52b6d17b",2178:"13069292",2217:"bfcd6182",2535:"deb92d63",3010:"f13ef9e9",3089:"27507abf",3130:"e3d45c8e",3237:"51fd0f1d",3259:"f1abd038",3505:"68271af5",3608:"d0c4985c",3636:"4a13cd1c",3751:"157c10ee",3893:"0378aba5",4013:"4d440933",4121:"d60a8749",4207:"76ec536b",4670:"1a86ede8",5068:"8ad7291e",5248:"e709f5cf",5625:"727df06d",6049:"6cfe5f17",6103:"14e91cbf",6181:"f1da1e65",6778:"88c755cd",7138:"3acae315",7149:"8d1aa85a",7251:"7d093eb3",7438:"57ce6924",7505:"c89628e1",7536:"1688c2d8",7813:"8a96939a",7847:"da52cc1e",7918:"afcca1a9",7920:"d094f34e",8068:"082d854d",8262:"fd127a03",8610:"319d29fe",8777:"10f7b1e7",8860:"13df6758",9127:"24e80eea",9360:"1c79147b",9372:"48e29085",9387:"33fbce5f",9514:"ed12907f",9671:"ca8cc1c8",9924:"f86b54c4"}[e]+".js",b.miniCssF=e=>{},b.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),b.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),t={},r="docs:",b.l=(e,c,a,d)=>{if(t[e])t[e].push(c);else{var f,o;if(void 0!==a)for(var n=document.getElementsByTagName("script"),i=0;i{f.onerror=f.onload=null,clearTimeout(s);var r=t[e];if(delete t[e],f.parentNode&&f.parentNode.removeChild(f),r&&r.forEach((e=>e(a))),c)return c(a)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:f}),12e4);f.onerror=l.bind(null,f.onerror),f.onload=l.bind(null,f.onload),o&&document.head.appendChild(f)}},b.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},b.p="/",b.gca=function(e){return e={17896441:"7918",72486833:"3505","935f2afb":"53",e665718d:"114",c276ecb2:"182","83d480e9":"205","6194ac84":"397",b2b675dd:"533","631e3189":"1241","382c5d2b":"1441",b2f554cd:"1477",a7023ddc:"1713","5087625a":"1724",ba322490:"2178",d7fbbe43:"2217","814f3328":"2535","56c3a9b2":"3010",a6aa9e1f:"3089",ac371aaa:"3130","1df93b7f":"3237","03ccf92d":"3259","9e4087bc":"3608","8b4dd820":"3636","3720c009":"3751","01a85c17":"4013","55960ee5":"4121",beebaad6:"4207",d83d689a:"5068","6101b3fc":"5248","657ac0bc":"5625",f213dd13:"6049",ccc49370:"6103","4e8ec325":"6181",cc591f25:"6778","38a042e4":"7138","822c343e":"7149",ba5b9f11:"7251","9c021584":"7438","8894e90f":"7505",f6e0e63c:"7536","933a69d3":"7813","43b416ef":"7847","1a4e3797":"7920","059d1c6a":"8262","6875c492":"8610","0d040286":"8860","9d9f8394":"9360","07f59c2a":"9372",b0f1c099:"9387","1be78505":"9514","0e384e19":"9671",df203c0f:"9924"}[e]||e,b.p+b.u(e)},(()=>{var e={1303:0,532:0};b.f.j=(c,a)=>{var t=b.o(e,c)?e[c]:void 0;if(0!==t)if(t)a.push(t[2]);else if(/^(1303|532)$/.test(c))e[c]=0;else{var r=new Promise(((a,r)=>t=e[c]=[a,r]));a.push(t[2]=r);var d=b.p+b.u(c),f=new Error;b.l(d,(a=>{if(b.o(e,c)&&(0!==(t=e[c])&&(e[c]=void 0),t)){var r=a&&("load"===a.type?"missing":a.type),d=a&&a.target&&a.target.src;f.message="Loading chunk "+c+" failed.\n("+r+": "+d+")",f.name="ChunkLoadError",f.type=r,f.request=d,t[1](f)}}),"chunk-"+c,c)}},b.O.j=c=>0===e[c];var c=(c,a)=>{var t,r,d=a[0],f=a[1],o=a[2],n=0;if(d.some((c=>0!==e[c]))){for(t in f)b.o(f,t)&&(b.m[t]=f[t]);if(o)var i=o(b)}for(c&&c(a);n{"use strict";var e,c,a,t,r,d={},f={};function b(e){var c=f[e];if(void 0!==c)return c.exports;var a=f[e]={exports:{}};return d[e].call(a.exports,a,a.exports,b),a.exports}b.m=d,e=[],b.O=(c,a,t,r)=>{if(!a){var d=1/0;for(i=0;i=r)&&Object.keys(b.O).every((e=>b.O[e](a[o])))?a.splice(o--,1):(f=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[a,t,r]},b.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return b.d(c,{a:c}),c},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,b.t=function(e,t){if(1&t&&(e=this(e)),8&t)return e;if("object"==typeof e&&e){if(4&t&&e.__esModule)return e;if(16&t&&"function"==typeof e.then)return e}var r=Object.create(null);b.r(r);var d={};c=c||[null,a({}),a([]),a(a)];for(var f=2&t&&e;"object"==typeof f&&!~c.indexOf(f);f=a(f))Object.getOwnPropertyNames(f).forEach((c=>d[c]=()=>e[c]));return d.default=()=>e,b.d(r,d),r},b.d=(e,c)=>{for(var a in c)b.o(c,a)&&!b.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:c[a]})},b.f={},b.e=e=>Promise.all(Object.keys(b.f).reduce(((c,a)=>(b.f[a](e,c),c)),[])),b.u=e=>"assets/js/"+({53:"935f2afb",114:"e665718d",182:"c276ecb2",205:"83d480e9",397:"6194ac84",533:"b2b675dd",1241:"631e3189",1441:"382c5d2b",1477:"b2f554cd",1713:"a7023ddc",1724:"5087625a",2178:"ba322490",2217:"d7fbbe43",2535:"814f3328",3010:"56c3a9b2",3089:"a6aa9e1f",3130:"ac371aaa",3237:"1df93b7f",3259:"03ccf92d",3505:"72486833",3608:"9e4087bc",3636:"8b4dd820",3751:"3720c009",4013:"01a85c17",4121:"55960ee5",4207:"beebaad6",5068:"d83d689a",5248:"6101b3fc",5625:"657ac0bc",6049:"f213dd13",6103:"ccc49370",6181:"4e8ec325",6778:"cc591f25",7138:"38a042e4",7149:"822c343e",7251:"ba5b9f11",7438:"9c021584",7505:"8894e90f",7536:"f6e0e63c",7813:"933a69d3",7847:"43b416ef",7918:"17896441",7920:"1a4e3797",8262:"059d1c6a",8610:"6875c492",8860:"0d040286",9360:"9d9f8394",9372:"07f59c2a",9387:"b0f1c099",9514:"1be78505",9671:"0e384e19",9924:"df203c0f"}[e]||e)+"."+{53:"f55b66bc",114:"45b00829",182:"90a09a09",205:"915fdb35",397:"32fdc436",533:"fb35fe43",1241:"51c5a947",1441:"11ebaefe",1477:"71472b0f",1713:"e7d703ab",1724:"0bb1a1ff",1769:"f0bfbb81",1947:"52b6d17b",2178:"13069292",2217:"bfcd6182",2535:"deb92d63",3010:"f13ef9e9",3089:"27507abf",3130:"e3d45c8e",3237:"51fd0f1d",3259:"f1abd038",3505:"68271af5",3608:"d0c4985c",3636:"4a13cd1c",3751:"157c10ee",3893:"0378aba5",4013:"4d440933",4121:"d60a8749",4207:"76ec536b",4670:"1a86ede8",5068:"8ad7291e",5248:"e709f5cf",5625:"727df06d",6049:"6cfe5f17",6103:"14e91cbf",6181:"f1da1e65",6778:"88c755cd",7138:"3e9357ca",7149:"8d1aa85a",7251:"7d093eb3",7438:"57ce6924",7505:"c89628e1",7536:"1688c2d8",7813:"8a96939a",7847:"da52cc1e",7918:"afcca1a9",7920:"d094f34e",8068:"082d854d",8262:"fd127a03",8610:"319d29fe",8777:"10f7b1e7",8860:"13df6758",9127:"24e80eea",9360:"1c79147b",9372:"48e29085",9387:"33fbce5f",9514:"ed12907f",9671:"ca8cc1c8",9924:"f86b54c4"}[e]+".js",b.miniCssF=e=>{},b.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),b.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),t={},r="docs:",b.l=(e,c,a,d)=>{if(t[e])t[e].push(c);else{var f,o;if(void 0!==a)for(var n=document.getElementsByTagName("script"),i=0;i{f.onerror=f.onload=null,clearTimeout(s);var r=t[e];if(delete t[e],f.parentNode&&f.parentNode.removeChild(f),r&&r.forEach((e=>e(a))),c)return c(a)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:f}),12e4);f.onerror=l.bind(null,f.onerror),f.onload=l.bind(null,f.onload),o&&document.head.appendChild(f)}},b.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},b.p="/",b.gca=function(e){return e={17896441:"7918",72486833:"3505","935f2afb":"53",e665718d:"114",c276ecb2:"182","83d480e9":"205","6194ac84":"397",b2b675dd:"533","631e3189":"1241","382c5d2b":"1441",b2f554cd:"1477",a7023ddc:"1713","5087625a":"1724",ba322490:"2178",d7fbbe43:"2217","814f3328":"2535","56c3a9b2":"3010",a6aa9e1f:"3089",ac371aaa:"3130","1df93b7f":"3237","03ccf92d":"3259","9e4087bc":"3608","8b4dd820":"3636","3720c009":"3751","01a85c17":"4013","55960ee5":"4121",beebaad6:"4207",d83d689a:"5068","6101b3fc":"5248","657ac0bc":"5625",f213dd13:"6049",ccc49370:"6103","4e8ec325":"6181",cc591f25:"6778","38a042e4":"7138","822c343e":"7149",ba5b9f11:"7251","9c021584":"7438","8894e90f":"7505",f6e0e63c:"7536","933a69d3":"7813","43b416ef":"7847","1a4e3797":"7920","059d1c6a":"8262","6875c492":"8610","0d040286":"8860","9d9f8394":"9360","07f59c2a":"9372",b0f1c099:"9387","1be78505":"9514","0e384e19":"9671",df203c0f:"9924"}[e]||e,b.p+b.u(e)},(()=>{var e={1303:0,532:0};b.f.j=(c,a)=>{var t=b.o(e,c)?e[c]:void 0;if(0!==t)if(t)a.push(t[2]);else if(/^(1303|532)$/.test(c))e[c]=0;else{var r=new Promise(((a,r)=>t=e[c]=[a,r]));a.push(t[2]=r);var d=b.p+b.u(c),f=new Error;b.l(d,(a=>{if(b.o(e,c)&&(0!==(t=e[c])&&(e[c]=void 0),t)){var r=a&&("load"===a.type?"missing":a.type),d=a&&a.target&&a.target.src;f.message="Loading chunk "+c+" failed.\n("+r+": "+d+")",f.name="ChunkLoadError",f.type=r,f.request=d,t[1](f)}}),"chunk-"+c,c)}},b.O.j=c=>0===e[c];var c=(c,a)=>{var t,r,d=a[0],f=a[1],o=a[2],n=0;if(d.some((c=>0!==e[c]))){for(t in f)b.o(f,t)&&(b.m[t]=f[t]);if(o)var i=o(b)}for(c&&c(a);n