1+ # Multi-stage build using kernel-images as base
2+ FROM docker.io/golang:1.25.0 AS server-builder
3+ WORKDIR /workspace/server
4+
5+ ARG TARGETOS
6+ ARG TARGETARCH
7+ ENV CGO_ENABLED=0
8+
9+ COPY kernel-images/server/go.mod ./
10+ COPY kernel-images/server/go.sum ./
11+ RUN go mod download
12+
13+ COPY kernel-images/server/ .
14+ RUN GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
15+ go build -ldflags="-s -w" -o /out/kernel-images-api ./cmd/api
16+
17+ # WebRTC client build
18+ FROM node:22-bullseye-slim AS client
19+ WORKDIR /src
20+ COPY kernel-images/images/chromium-headful/client/package*.json ./
21+ RUN npm install
22+ COPY kernel-images/images/chromium-headful/client/ .
23+ RUN npm run build
24+
25+ # Xorg dependencies
26+ FROM docker.io/ubuntu:22.04 AS xorg-deps
27+ WORKDIR /xorg
28+ ENV DEBIAN_FRONTEND=noninteractive
29+ RUN set -eux; \
30+ apt-get update; \
31+ apt-get install -y \
32+ git gcc pkgconf autoconf automake libtool make xorg-dev xutils-dev \
33+ && rm -rf /var/lib/apt/lists/*;
34+ COPY kernel-images/images/chromium-headful/xorg-deps/ /xorg/
35+ # build xf86-video-dummy v0.3.8 with RandR support
36+ RUN set -eux; \
37+ cd xf86-video-dummy/v0.3.8; \
38+ patch -p1 < ../01_v0.3.8_xdummy-randr.patch; \
39+ autoreconf -v --install; \
40+ ./configure; \
41+ make -j$(nproc); \
42+ make install;
43+ # build custom input driver
44+ RUN set -eux; \
45+ cd xf86-input-neko; \
46+ ./autogen.sh --prefix=/usr; \
47+ ./configure; \
48+ make -j$(nproc); \
49+ make install;
50+
51+ FROM ghcr.io/onkernel/neko/base:3.0.6-v1.0.1 AS neko
52+
53+ # Main Cloud Run stage
54+ FROM docker.io/ubuntu:22.04
55+
56+ ENV DEBIAN_FRONTEND=noninteractive
57+ ENV DEBIAN_PRIORITY=high
58+
59+ # Install all dependencies including nginx for port proxying
60+ RUN apt-get update && \
61+ apt-get -y upgrade && \
62+ apt-get -y install \
63+ # UI Requirements
64+ xvfb \
65+ xterm \
66+ xdotool \
67+ scrot \
68+ imagemagick \
69+ sudo \
70+ mutter \
71+ # Python/pyenv reqs
72+ build-essential \
73+ libssl-dev \
74+ zlib1g-dev \
75+ libbz2-dev \
76+ libreadline-dev \
77+ libsqlite3-dev \
78+ curl \
79+ git \
80+ libncursesw5-dev \
81+ xz-utils \
82+ tk-dev \
83+ libxml2-dev \
84+ libxmlsec1-dev \
85+ libffi-dev \
86+ liblzma-dev \
87+ # Network tools
88+ net-tools \
89+ netcat \
90+ nginx \
91+ # PPA req
92+ software-properties-common && \
93+ # Userland apps
94+ sudo add-apt-repository ppa:mozillateam/ppa && \
95+ sudo apt-get install -y --no-install-recommends \
96+ chromium-browser \
97+ libreoffice \
98+ x11-apps \
99+ xpdf \
100+ gedit \
101+ xpaint \
102+ tint2 \
103+ galculator \
104+ pcmanfm \
105+ wget \
106+ xdg-utils \
107+ libvulkan1 \
108+ fonts-liberation \
109+ unzip && \
110+ apt-get clean
111+
112+ # Install ffmpeg manually
113+ RUN set -eux; \
114+ URL="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz"; \
115+ echo "Downloading FFmpeg static build from $URL"; \
116+ curl -fsSL "$URL" -o /tmp/ffmpeg.tar.xz; \
117+ tar -xJf /tmp/ffmpeg.tar.xz -C /tmp; \
118+ install -m755 /tmp/ffmpeg-*/ffmpeg /usr/local/bin/ffmpeg; \
119+ install -m755 /tmp/ffmpeg-*/ffprobe /usr/local/bin/ffprobe; \
120+ rm -rf /tmp/ffmpeg*
121+
122+ # Create kernel user first
123+ RUN useradd -m -s /bin/bash kernel
124+
125+ # Runtime dependencies
126+ ENV USERNAME=kernel
127+ RUN set -eux; \
128+ apt-get update; \
129+ apt-get install -y --no-install-recommends \
130+ wget ca-certificates python2 supervisor xclip xdotool \
131+ pulseaudio dbus-x11 xserver-xorg-video-dummy \
132+ libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
133+ gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
134+ gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
135+ gstreamer1.0-pulseaudio gstreamer1.0-omx; \
136+ #
137+ # install libxcvt0 (not available in debian:bullseye)
138+ ARCH=$(dpkg --print-architecture); \
139+ wget http://ftp.de.debian.org/debian/pool/main/libx/libxcvt/libxcvt0_0.1.2-1_${ARCH}.deb; \
140+ apt-get install --no-install-recommends ./libxcvt0_0.1.2-1_${ARCH}.deb; \
141+ rm ./libxcvt0_0.1.2-1_${ARCH}.deb; \
142+ #
143+ # workaround for an X11 problem: http://blog.tigerteufel.de/?p=476
144+ mkdir /tmp/.X11-unix; \
145+ chmod 1777 /tmp/.X11-unix; \
146+ chown $USERNAME /tmp/.X11-unix/; \
147+ #
148+ # make directories for neko
149+ mkdir -p /etc/neko /var/www /var/log/neko \
150+ /tmp/runtime-$USERNAME \
151+ /home/$USERNAME/.config/pulse \
152+ /home/$USERNAME/.local/share/xorg; \
153+ chmod 1777 /var/log/neko; \
154+ chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
155+ chown -R $USERNAME:$USERNAME /home/$USERNAME; \
156+ # clean up
157+ apt-get clean -y; \
158+ rm -rf /var/lib/apt/lists/* /var/cache/apt/
159+
160+ # Install chromium and sqlite3 for debugging the cookies file
161+ RUN add-apt-repository -y ppa:xtradeb/apps
162+ RUN apt update -y && apt install -y chromium sqlite3
163+
164+ # Setup desktop env & app - Cloud Run specific
165+ ENV DISPLAY_NUM=1
166+ ENV HEIGHT=768
167+ ENV WIDTH=1024
168+ ENV WITHDOCKER=true
169+ ENV PORT=8080
170+
171+ # Copy configurations
172+ COPY kernel-images/images/chromium-headful/xorg.conf /etc/neko/xorg.conf
173+ COPY kernel-images/images/chromium-headful/neko.yaml /etc/neko/neko.yaml
174+ COPY --from=neko /usr/bin/neko /usr/bin/neko
175+ COPY --from=client /src/dist/ /var/www
176+ COPY --from=xorg-deps /usr/local/lib/xorg/modules/drivers/dummy_drv.so /usr/lib/xorg/modules/drivers/dummy_drv.so
177+ COPY --from=xorg-deps /usr/local/lib/xorg/modules/input/neko_drv.so /usr/lib/xorg/modules/input/neko_drv.so
178+
179+ COPY kernel-images/images/chromium-headful/image-chromium/ /
180+ COPY kernel-images/images/chromium-headful/start-chromium.sh /images/chromium-headful/start-chromium.sh
181+ RUN chmod +x /images/chromium-headful/start-chromium.sh
182+ COPY kernel-images/images/chromium-headful/supervisord.conf /etc/supervisor/supervisord.conf
183+ COPY supervisord-cloudrun.conf /etc/supervisor/supervisord-cloudrun.conf
184+ COPY kernel-images/images/chromium-headful/supervisor/services/ /etc/supervisor/conf.d/services/
185+
186+ # Copy the kernel-images API binary
187+ COPY --from=server-builder /out/kernel-images-api /usr/local/bin/kernel-images-api
188+
189+ # Cloud Run specific: nginx configuration for port proxying
190+ COPY nginx.conf /etc/nginx/nginx.conf
191+ COPY cloudrun-wrapper.sh /cloudrun-wrapper.sh
192+ RUN chmod +x /cloudrun-wrapper.sh
193+
194+ # Create nginx temp directories for non-root execution
195+ RUN mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_temp \
196+ /tmp/nginx_uwsgi_temp /tmp/nginx_scgi_temp && \
197+ chown -R kernel:kernel /tmp/nginx_*
198+
199+ # Create supervisor log directories
200+ RUN mkdir -p /var/log/supervisord/chromium /var/log/supervisord/neko /var/log/supervisord/xorg \
201+ /var/log/supervisord/dbus /var/log/supervisord/kernel-images-api /var/log/supervisord/mutter && \
202+ chown -R kernel:kernel /var/log/supervisord
203+
204+ # Create health check endpoint
205+ RUN echo '#!/bin/bash\necho "OK"' > /usr/local/bin/health-check && chmod +x /usr/local/bin/health-check
206+
207+ # Cloud Run requires non-root execution
208+ USER kernel
209+
210+ EXPOSE 8080
211+
212+ ENTRYPOINT ["/cloudrun-wrapper.sh"]
0 commit comments