I’m trying to use a docker container to grade student-submitted homework assignments in. I have roughly 200 submissions, each of which needs to be run from a consistent starting point, since each submission can delete files/directories, make new ones, or potentially mess something up on the system.
What I’m doing currently is I have a dockerfile with the following content
FROM ubuntu
WORKDIR /root/app
COPY . .
RUN apt-get update && apt-get upgrade -y
#TODO: Set up directory structure using RUN with touch, mkdir, ln, etc.
What I’m currently planning is to call the following command on each submitted script (from a python script that iterates over the submissions, captures the output, and grades each submission based on it):
docker run --rm image-name ./scriptname.sh arg1 arg2
I added the --rm flag because otherwise, the containers populate the docker ps table, so they apparently remain saved after exiting (even though I can’t restart them – running docker start and docker attach complains that I can’t attach to a stopped container), so I’d just end up with 200+ rogue containers on my system.
However, this seems to be quite slow. Can such a sequence of runs be sped up in some way? I thought of doing docker start image-name and then replacing the docker run command with docker exec for each submission, but I’m assuming this wouldn’t recreate the initial file structure for each submission?
Just as a side note as this was not your question, but never run apt upgrade in a container. That can break something or even introduce new security issues bugs which were not tested. Not to mention that layer would run only once and never after that. I guess this is why you put the copy command before it which just makes the build slower. Also never use the latest tag or the image name without any tag (which will be the latest tag) because that is uncontrollable and you will end up with a new ubuntu release and break everything. Build specific versions and regurarly check new versions to rebuild your image.
After that huge side note, let’s get back to the question.
You probably can but it fails or runs in the background. Check the output of docker logs containername. Docker start starts the containers in the background unless passing -a.
That would be docker run image-name and docker exec. You don’t need docker start or if you need, you will use docker start container-name not image-name.
For that to work, you need something in the container that keeps it alive while you run docker exec. For example:
docker run -d --init --name container-name image-name sleep inf
When you are done, you can remove the container (docker rm -f container-name or stop it (docker stop container-name). If you just stop it, you can indeed use docker start container-name to start it again later. If you remove it, then you can recreate the container with the same command and it will not be kept in the container list when you don’t need it.