Hello I am trying to build an image which can compile and run a c++ program securely.
FROM golang:latest as builder
WORKDIR /app
COPY . .
RUN go mod download
RUN env CGO_ENABLED=0 go build -o /worker
FROM alpine:latest
RUN apk update && apk add --no-cache g++ && apk add --no-cache tzdata
ENV TZ=Asia/Kolkata
WORKDIR /
COPY --from=builder worker /bin
ARG USER=default
RUN addgroup -S $USER && adduser -S $USER -G $USER
USER $USER
ENTRYPOINT [ "worker" ]
version: "3.9"
services:
gpp:
build: .
environment:
- token=test_token
- code=#include <iostream>rnrnusing namespace std;rnrnint main() {rn int a = 10;rn int b = 20;rn cout << a << " " << b << endl;rn int temp = a;rn a = b;rn b = temp;rn cout << a << " " << b << endl;rn return 0;rn}
network_mode: bridge
privileged: false
read_only: true
tmpfs: /tmp
security_opt:
- "no-new-privileges"
cap_drop:
- "all"
Here worker is a golang binary which reads code from environment variable and stores it in /tmp folder as main.cpp, and then tries to compile and run it using g++ /tmp/main.cpp
&& ./tmp/a.out
(using golang exec)
I am getting this error scratch_4-gpp-1 | Error : fork/exec /tmp/a.out: permission denied
, from which what I can understand / know that executing anything from tmp directory is restricted.
Since, I am using read_only root file system, I can only work on tmp directory, Please guide me how I can achieve above task keeping my container secured.
2
Answers
Complete summary of solution -
@davidmaze mentioned to add an anonymous volume using
as I replied I am still getting an error
Cannot create temporary file in ./: Read-only file system
when I tried to compile my program. When I debugged my container to see file system changes inread_only:false
mode, I found that compiler is trying to save thea.out
file in/bin
folder, which is suppose to be read only.So I added this additional line before the entry point and my issue was solved.
Docker’s default options for a tmpfs include
noexec
.docker run --tmpfs
allows an extended set of mount options, but neither Composetmpfs:
nor the extended syntax ofvolumes:
allows changing anything other than the size option.One straightforward option here is to use an anonymous volume. Syntactically this looks like a normal
volumes:
line, except it only has a container path. Theread_only:
option will make the container’s root filesystem be read-only, but volumes are exempted from this.This will be a "normal" Docker volume, so it will be disk-backed and you’ll be able to see it in
docker volume ls
.