diff --git a/content/hackathons/usw24/index.mdx b/content/hackathons/usw24/index.mdx index 5d6d5f6b..b2468f6d 100644 --- a/content/hackathons/usw24/index.mdx +++ b/content/hackathons/usw24/index.mdx @@ -397,6 +397,131 @@ Use the `hugo` setup from the last session. Follow the steps for debugging messages and gdb for [`node`](https://github.com/unikraft/catalog/tree/main/library/node/21). Use the `node` setup from the last session. +### Session 06: Porting an Application + +Now that we have learned how to debug Unikraft applications, we can move on to porting some more complex applications, that might require more then we have seen in the third session. +The workflow for porting an application is the same as the one in the third session: create a `Dockerfile`, add a `Kraftfile`, create a minimal filesystem and run the application on top of Unikraft. +Sometimes, the minimal filesystem can not be created corectly whithout running the application, so we will make use of the debugging messages from the last session. + +Let's take `nginx` as an example. +We start from the already existing [`nginx` port](https://github.com/unikraft/catalog/blob/main/library/nginx/1.25) and we remove the `Dockerfile`, since we will write that ourselves. + +Next, we start a docker container from the `nginx` official image: + +```console +docker run --rm -it nginx:1.25.3-bookworm /bin/bash +``` + +We use `ldd` to get the dependencies: + +```console +$ ldd /usr/sbin/nginx + linux-vdso.so.1 (0x00007ffdf39e8000) + libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x000073162deb9000) + libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x000073162de1f000) + libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x000073162dd75000) + libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x000073162d8f3000) + libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x000073162d8d4000) + libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000073162d6f1000) + /lib64/ld-linux-x86-64.so.2 (0x000073162e133000) +``` + +Next, we create a `Dockerfile` where we copy the dependencies to a scratch image: + +```text +FROM nginx:1.25.3-bookworm AS build + +FROM scratch + +COPY --from=build /usr/sbin/nginx /usr/bin/nginx +COPY --from=build /usr/lib/nginx /usr/lib/nginx + +# Libraries +COPY --from=build /lib/x86_64-linux-gnu/libcrypt.so.1 /lib/x86_64-linux-gnu/libcrypt.so.1 +COPY --from=build /lib/x86_64-linux-gnu/libpcre2-8.so.0 /lib/x86_64-linux-gnu/libpcre2-8.so.0 +COPY --from=build /lib/x86_64-linux-gnu/libssl.so.3 /lib/x86_64-linux-gnu/libssl.so.3 +COPY --from=build /lib/x86_64-linux-gnu/libcrypto.so.3 /lib/x86_64-linux-gnu/libcrypto.so.3 +COPY --from=build /lib/x86_64-linux-gnu/libz.so.1 /lib/x86_64-linux-gnu/libz.so.1 +COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 +COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 +COPY --from=build /etc/ld.so.cache /etc/ld.so.cache +``` + +Then, to enable debug messages, we uncomment [this line](https://github.com/unikraft/catalog/blob/main/library/nginx/1.25/Kraftfile#L112) from the `Kraftfile`. + +Now, we can run `kraft build` and `kraft run`, to see if the application works. +We will get an error message: + +```text +openat(AT_FDCWD, "/etc/nginx/nginx.conf", O_RDONLY) = No such file or directory (-2) +gettid() = pid:1 +2024/07/12 08:11:50 [emerg] 1#1: open() "/etc/nginx/nginx.conf" failed (2: No such file or directory) +``` + +This tells us that `nginx` will look for a config file. +We have a minimal config in the [`conf/`](https://github.com/unikraft/catalog/tree/main/library/nginx/1.25/conf) directory, so we copy that too, adding this line in the `Dockerfile`: + +```text +COPY ./conf/nginx.conf /etc/nginx/nginx.conf +``` + +We do `kraft build` and `kraft run` again, and we get another message: + +```text +openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = No such file or directory (-2) +gettid() = pid:1 +2024/07/12 08:19:32 [emerg] 1#1: getpwnam("root") failed (2: No such file or directory) in /etc/nginx/nginx.conf:4 +``` + +This tells us that `getpwnam("root")` failed, because no `/etc/passwd` and `/etc/group` files are provided, so we also add those in the `Dockerfile`: + +```text +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group +``` + +We rebuild and run again, and get: + +```text +2024/07/12 08:25:31 [emerg] 1#1: open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:11 +``` + +So we add `/etc/nginx/` to the filesystem: + +```text +COPY --from=build /etc/nginx /etc/nginx +``` + +We repeat the same process and find out more requirements for our application: + +```text +COPY --from=build /var/cache/nginx /var/cache/nginx +COPY --from=build /var/run /var/run +COPY --from=build /usr/lib/nginx /usr/lib/nginx +COPY --from=build /var/log/nginx /var/log/nginx +``` + +After that, the application seems to run properly. +We use `kraft run -p 8080:80` and then, from another terminal, we run `curl localhost:8080` and we get a `404` page response. +This is because we also need to add an initial page for `nginx` to serve. +We have that already under `wwwroot/`, and we add that to the `Dockerfile`: + +```text +COPY ./wwwroot /wwwroot +``` + +After that, everything should work properly. + +#### `node` + +Now that you have seen how porting an application works, you can try it yourself with the [`node`](https://github.com/unikraft/catalog/tree/main/library/node/21) application. +Remove the `Dockerfile`, start from the `node:21-alpine` image and follow the same steps as above. + +#### `memcached` + +Do the same for [`memcached`](https://github.com/unikraft/catalog/blob/main/library/memcached/1.6/). +Remove the `Dockerfile` and start from `memcached:1.6.23-bookworm`. + ### Session Recordings You can check the recordings of the initial presentations for each session on [YouTube](https://www.youtube.com/playlist?list=PL0ZXUYDfkQ61ezmByQNLlzJ8s_dkJmQ1S).