-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathDockerfile
207 lines (191 loc) · 9.74 KB
/
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
########################################################################################################################
# Build stage for rust backend
########################################################################################################################
FROM rust:alpine AS builder
ARG TARGETPLATFORM
RUN apk update && \
apk add --no-cache \
musl-dev \
gcc
WORKDIR /usr/src/qemu-backend
COPY ./web-backend .
# Build the application for musl
RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
rustup target add aarch64-unknown-linux-musl; \
else \
rustup target add x86_64-unknown-linux-musl; \
fi
# Build the application for the specific target architecture
RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
cargo build --release --target aarch64-unknown-linux-musl; \
cp /usr/src/qemu-backend/target/aarch64-unknown-linux-musl/release/qemu-openwrt-web-backend /usr/local/bin; \
else \
cargo build --release --target x86_64-unknown-linux-musl; \
cp /usr/src/qemu-backend/target/x86_64-unknown-linux-musl/release/qemu-openwrt-web-backend /usr/local/bin; \
fi
########################################################################################################################
# OpenWrt image
########################################################################################################################
FROM alpine:latest
ARG NOVNC_VERSION="1.5.0"
ARG OPENWRT_VERSION="24.10.0"
ARG TARGETPLATFORM
ARG OPENWRT_ROOTFS_IMG
ARG OPENWRT_KERNEL
ARG OPENWRT_ROOTFS_TAR
# Configure Alpine
RUN echo "Building for platform '$TARGETPLATFORM'" \
&& if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
CPU_ARCH="x86_64"; \
APK_EXTRA="ovmf"; \
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
CPU_ARCH="aarch64"; \
APK_EXTRA=""; \
else \
echo "Error: CPU architecture $TARGETPLATFORM is not supported"; \
exit 1; \
fi \
&& apk add --no-cache \
multirun \
bash \
wget \
grep \
qemu-system-"$CPU_ARCH" \
qemu-hw-usb-host \
qemu-hw-usb-redirect \
nginx \
nginx-mod-stream \
netcat-openbsd \
uuidgen \
usbutils \
pciutils \
openssh-client \
util-linux-misc \
iproute2 \
"$APK_EXTRA" \
# It seems that PROFINET packages are not forwarded correctly without the package iproute2. The reason is unknown. \
&& mkdir -p /usr/share/novnc \
&& wget https://github.com/novnc/noVNC/archive/refs/tags/v${NOVNC_VERSION}.tar.gz -O /tmp/novnc.tar.gz -q \
&& tar -xf /tmp/novnc.tar.gz -C /tmp/ \
&& cd /tmp/noVNC-${NOVNC_VERSION}\
&& mv app core vendor package.json *.html /usr/share/novnc \
&& sed -i 's/^worker_processes.*/worker_processes 1;daemon off;/' /etc/nginx/nginx.conf
COPY ./openwrt_additional /var/vm/openwrt_additional
# Handle different CPUs architectures and choose the correct OpenWrt images
RUN echo "Building for platform '$TARGETPLATFORM'" \
&& if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
if [ "$OPENWRT_VERSION" = "master" ]; then \
OPENWRT_IMAGE="https://downloads.openwrt.org/snapshots/targets/x86/64/openwrt-x86-64-generic-squashfs-combined-efi.img.gz"; \
elif [ "$OPENWRT_VERSION" = "24.10-SNAPSHOT" ]; then \
wget https://downloads.openwrt.org/releases/24.10-SNAPSHOT/targets/x86/64/version.buildinfo; \
VERSION_BUILDINFO=`cat version.buildinfo`; \
OPENWRT_IMAGE="https://downloads.openwrt.org/releases/24.10-SNAPSHOT/targets/x86/64/openwrt-24.10-snapshot-${VERSION_BUILDINFO}-x86-64-generic-squashfs-combined-efi.img.gz"; \
else \
OPENWRT_IMAGE="https://archive.openwrt.org/releases/${OPENWRT_VERSION}/targets/x86/64/openwrt-${OPENWRT_VERSION}-x86-64-generic-squashfs-combined-efi.img.gz"; \
fi; \
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
if [ "$OPENWRT_VERSION" = "master" ]; then \
OPENWRT_IMAGE="https://downloads.openwrt.org/snapshots/targets/armsr/armv8/openwrt-armsr-armv8-generic-squashfs-combined-efi.img.gz"; \
elif [ "$OPENWRT_VERSION" = "24.10-SNAPSHOT" ]; then \
wget https://downloads.openwrt.org/releases/24.10-SNAPSHOT/targets/armsr/armv8/version.buildinfo; \
VERSION_BUILDINFO=`cat version.buildinfo`; \
OPENWRT_IMAGE="https://downloads.openwrt.org/releases/24.10-SNAPSHOT/targets/armsr/armv8/openwrt-24.10-snapshot-${VERSION_BUILDINFO}-armsr-armv8-generic-squashfs-combined-efi.img.gz"; \
else \
OPENWRT_IMAGE="https://archive.openwrt.org/releases/${OPENWRT_VERSION}/targets/armsr/armv8/openwrt-${OPENWRT_VERSION}-armsr-armv8-generic-squashfs-combined-efi.img.gz"; \
fi; \
else \
echo "Error: CPU architecture $TARGETPLATFORM is not supported"; \
exit 1; \
fi \
\
# Get OpenWrt images \
&& wget $OPENWRT_IMAGE -O /var/vm/squashfs-combined-${OPENWRT_VERSION}.img.gz \
&& gzip -d /var/vm/squashfs-combined-${OPENWRT_VERSION}.img.gz \
\
# Each CPU architecture needs a different SSH port to make a possible to make a parallel build \
&& SSH_PORT=1022 \
\
# Boot OpenWrt in order to install additional packages and settings \
&& if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
SSH_PORT=1022; \
qemu-system-x86_64 -M pc -nographic -nodefaults -m 256 \
-bios /usr/share/ovmf/bios.bin \
-blockdev driver=raw,node-name=hd0,cache.direct=on,file.driver=file,file.filename=/var/vm/squashfs-combined-${OPENWRT_VERSION}.img \
-device virtio-blk-pci,drive=hd0 \
-device virtio-net,netdev=qlan0 -netdev user,id=qlan0,net=192.168.1.0/24,hostfwd=tcp::$SSH_PORT-192.168.1.1:22 \
-device virtio-net,netdev=qwan0 -netdev user,id=qwan0 \
& QEMU_PID=$!; \
else \
SSH_PORT=2022; \
qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -nodefaults -m 256 \
-bios /usr/share/qemu/edk2-aarch64-code.fd \
-blockdev driver=raw,node-name=hd0,cache.direct=on,file.driver=file,file.filename=/var/vm/squashfs-combined-${OPENWRT_VERSION}.img \
-device virtio-blk-pci,drive=hd0 \
-device virtio-net,netdev=qlan0 -netdev user,id=qlan0,net=192.168.1.0/24,hostfwd=tcp::$SSH_PORT-192.168.1.1:22 \
-device virtio-net,netdev=qwan0 -netdev user,id=qwan0 \
& QEMU_PID=$!; \
fi \
&& echo "QEMU started with PID $QEMU_PID" \
\
# OpenWrt master uses apk insted of opkg \
&& if [ "$OPENWRT_VERSION" = "master" ]; then \
PACKAGE_UPDATE="apk update"; \
PACKAGE_INSTALL="apk add"; \
PACKAGE_REMOVE="apk del"; \
PACKAGE_EXTRA="libudev-zero"; \
else \
PACKAGE_UPDATE="opkg update"; \
PACKAGE_INSTALL="opkg install"; \
PACKAGE_REMOVE="opkg remove"; \
PACKAGE_EXTRA=""; \
fi \
\
# Wait for OpenWrt startup and update repo \
&& until ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new root@localhost -p $SSH_PORT "cat /etc/banner"; do echo "Waiting for OpenWrt boot ..."; sleep 1; done \
# Update package repo. Some some reasons it can fail. So try it until we are successfull. \
&& until ssh root@localhost -p $SSH_PORT "${PACKAGE_UPDATE}"; do echo "Retrying ${PACKAGE_UPDATE} ..."; sleep 1; done\
# Download Luci, qemu guest agent and mDNS support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} qemu-ga luci luci-ssl umdns losetup ${PACKAGE_EXTRA}" \
# Download USB, PCI and PCIe support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} usbutils pciutils" \
# Download Wi-Fi access point support and Wi-Fi USB devices support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} hostapd wpa-supplicant kmod-mt7921u" \
# Download celluar network support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} modemmanager kmod-usb-net-qmi-wwan luci-proto-modemmanager qmi-utils" \
# Download basic GPS support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} kmod-usb-serial minicom gpsd" \
# Add Wireguard support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} wireguard-tools luci-proto-wireguard" \
# Add Power off script support \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} luci-app-advanced-reboot" \
\
# Add default network config \
&& ssh root@localhost -p $SSH_PORT "uci set network.lan.ipaddr='172.31.1.1'; uci commit network" \
\
# Add some files \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_INSTALL} openssh-sftp-server" \
&& chmod +x /var/vm/openwrt_additional/usr/bin/* \
&& scp -P $SSH_PORT /var/vm/openwrt_additional/usr/bin/* root@localhost:/usr/bin \
&& ssh root@localhost -p $SSH_PORT "${PACKAGE_REMOVE} openssh-sftp-server" \
\
# Sync changes into image and shutdown qemu \
&& ssh root@localhost -p $SSH_PORT 'sync; halt' \
&& while kill -0 $QEMU_PID 2>/dev/null; do echo "Waiting for qemu exit ..."; sleep 1; done \
\
&& gzip /var/vm/squashfs-combined-${OPENWRT_VERSION}.img \
\
&& echo "OPENWRT_VERSION=\"${OPENWRT_VERSION}\"" > /var/vm/openwrt_metadata.conf \
&& echo "OPENWRT_IMAGE_CREATE_DATETIME=\"`date`\"" >> /var/vm/openwrt_metadata.conf \
&& echo "OPENWRT_IMAGE_ID=\"`uuidgen`\"" >> /var/vm/openwrt_metadata.conf \
&& echo "OPENWRT_CPU_ARCH=\"${TARGETPLATFORM}\"" >> /var/vm/openwrt_metadata.conf \
&& echo "CONTAINER_CREATE_DATETIME=\"`date`\"" >> /var/vm/openwrt_metadata.conf
COPY --from=builder /usr/local/bin/qemu-openwrt-web-backend /usr/local/bin/qemu-openwrt-web-backend
COPY ./src /run/
COPY ./web-frontend /var/www/
RUN chmod +x /run/*.sh
VOLUME /storage
EXPOSE 8006
EXPOSE 8000
EXPOSE 8022
HEALTHCHECK --start-period=10m CMD /run/healthcheck.sh
CMD ["/run/init_container.sh"]