skip to Main Content

I’m creating a website similar to leetcode where users can submit code. I’ll be running this code in a docker container for security measures. My code isn’t behaving how I was expecting it to. I’ve written this script which displays the problem. Also I’m doing this on an m1 macbook.

Expected behaviour:

  • Print contents of current directory
  • Creates a docker container and copies test_file.py into it from the current directory.
  • Runs test_file.py and prints the stdout of the container to my console.

What happens:

  • Print contents of current directory (including test_file.py)
  • Docker can’t find test_file.py

main.py:

import subprocess

dockerfile_content = f"""
FROM python:3.9-slim

WORKDIR /app

COPY ./test_file.py /app/test_file.py

CMD ["python", "app/test_file.py"]
"""

# Docker image and container names
image_name = 'image_name'
container_name = 'conainer_name'

# Build the Docker image
subprocess.run(['ls'])
build_process = subprocess.Popen(['docker', 'build', '-t', image_name, "-"], stdin=subprocess.PIPE)
build_process.communicate(input=dockerfile_content.encode())

# Run the Docker container
result = subprocess.run(['docker', 'run', '--name', container_name, image_name], capture_output=True, text=True)
print('STDOUT:', result.stdout)
print('STDERR:', result.stderr)

# Clean up: remove container and image
subprocess.run(['docker', 'rm', container_name], check=False)
subprocess.run(['docker', 'rmi', image_name], check=False)

Output:

test_file.py main.py
+] Building 1.1s (7/7) FINISHED                                                                                   docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                               0.0s
 => => transferring dockerfile: 148B                                                                                               0.0s
 => [internal] load metadata for docker.io/library/python:3.9-slim                                                                 1.1s
 => [internal] load .dockerignore                                                                                                  0.0s
 => => transferring context: 2B                                                                                                    0.0s
 => [1/3] FROM docker.io/library/python:3.9-slim@sha256:d3185e5aa645a4ff0b52416af05c8465d93791e49c5a0d0f565c119099f26cde           0.0s
 => => resolve docker.io/library/python:3.9-slim@sha256:d3185e5aa645a4ff0b52416af05c8465d93791e49c5a0d0f565c119099f26cde           0.0s
 => [internal] load build context                                                                                                  0.0s
 => => transferring context: 2B                                                                                                    0.0s
 => CACHED [2/3] WORKDIR /app                                                                                                      0.0s
 => ERROR [3/3] COPY ./test_file.py /app/test_file.py                                                                              0.0s
------
 > [3/3] COPY ./test_file.py /app/test_file.py:
------
Dockerfile:6
--------------------
   4 |     WORKDIR /app
   5 |     
   6 | >>> COPY ./test_file.py /app/test_file.py
   7 |     
   8 |     CMD ["python", "app/test_file.py"]
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref d7cab07d-c12c-40fd-80e6-5ccd8b3c75df::nufuebj2yhxnpjfnizar2q5go: "/test_file.py": not found
STDOUT: 
STDERR: Unable to find image 'image_name:latest' locally
docker: Error response from daemon: pull access denied for image_name, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.

Error response from daemon: No such container: conainer_name
Error response from daemon: No such image: image_name:latest

2

Answers


  1. When you run docker build, you are invoking it as docker build -. This takes the Dockerfile on stdin, but it doesn’t otherwise have access to any filesystem content; there are no files that you can COPY into the image.

    If you’ve the source file is in the current directory, you should pass the current directory . as the build-context argument instead. You’re not passing anything to stdin in this case.

    subprocess.run(['docker', 'build', '-t', image_name, "."], check=True)
    

    I’ve made a couple of changes here. I’ve changed to subprocess.run() to do a blocking call. I’ve changed the last argument from - to ., to pass the current directory. I’ve also added check=True to the end, so your Python code will stop with an exception if the image build fails.

    You can pass any directory as the last argument, so you could use a tempfile.TemporaryDirectory too. Your system may be more robust if you use the Docker SDK for Python instead of trying to use subprocess to invoke the Docker CLI; this will let you do things like get the IDs of anonymous images and containers programmatically, without needing to parse the docker CLI output.

    Login or Signup to reply.
  2. So based on your script, Docker creates a temporary virtual build context in memory. This context is empty except for the Dockerfile content you provide through stdin. Because the virtual build context is empty, any COPY instructions in your Dockerfile that try to copy files will fail.

    I think you could write the dockerfile_content to a temporary file, then provide the directory containing that temporary file as the build context when you call docker build.

    However, I would just create a seperate Dockerfile in the same folder, then modify the main.py script to run "Docker build -t container_name". If Dockerfile needs to be in the other folder, you will need to supply the path to the Dockerfile and the current build context.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search