-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathDockerfile
More file actions
230 lines (209 loc) · 10.6 KB
/
Dockerfile
File metadata and controls
230 lines (209 loc) · 10.6 KB
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
########################################################################################################################
# Build stage for rust backend
########################################################################################################################
FROM rust:alpine AS build-backend
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
########################################################################################################################
# Build stage for angular frontend
########################################################################################################################
FROM node:latest AS build-frontend
WORKDIR /usr/local/app
COPY ./web-frontend /usr/local/app/
# See https://github.com/nodejs/docker-node/issues/1668
RUN npm update -g npm
RUN npm ci --no-audit --maxsockets 1
RUN npm install
RUN npm run build -- "--base-href='./'"
########################################################################################################################
# OpenWrt image
########################################################################################################################
FROM alpine:latest
ARG OPENWRT_VERSION="25.12.3"
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. \
&& 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://downloads.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://downloads.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 \
\
# 4k align the OpenWrt image so qemu doesn't complain about resize errors \
# Get current size in bytes \
&& size=$(stat -c%s "/var/vm/squashfs-combined-${OPENWRT_VERSION}.img") \
# ceil to MB \
&& size_mb=$(( (size + 1024*1024 - 1) / (1024*1024) )) \
&& echo "Current size: ${size_mb} MiB " \
# Decide target size \
&& if [ "$size_mb" -le 128 ]; then \
target_mb=128; \
elif [ "$size_mb" -le 256 ]; then \
target_mb=256; \
elif [ "$size_mb" -le 512 ]; then \
target_mb=512; \
elif [ "$size_mb" -le 1024 ]; then \
target_mb=1024; \
fi \
&& echo "Extending /var/vm/squashfs-combined-${OPENWRT_VERSION}.img to ${target_mb} MiB..." \
&& dd if=/dev/zero of="/var/vm/squashfs-combined-${OPENWRT_VERSION}.img" seek="${target_mb}" obs=1M count=0 \
\
# 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 uses apk now \
&& PACKAGE_UPDATE="apk update" \
&& PACKAGE_INSTALL="apk add" \
&& PACKAGE_REMOVE="apk del" \
&& PACKAGE_EXTRA="libudev-zero" \
\
# 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/24'; 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; poweroff' \
&& 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=build-backend /usr/local/bin/qemu-openwrt-web-backend /usr/local/bin/qemu-openwrt-web-backend
COPY --from=build-frontend /usr/local/app/dist/openwrt-docker-web-gui /var/www/
COPY ./web-frontend/nginx* /var/www/
COPY ./src /run/
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"]