Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to 'docker exec' a container built from scratch?

I am trying to docker exec a container that is built from scratch (say, a NATS container). Seems pretty straight-forward, but since it is built from scratch, I am unable to access /bin/bash, /bin/sh and literally any such command.

I get the error: oci runtime error (command not found, file not found, etc. depending upon the command that I enter).

I tried some commands like:

docker exec -it <container name> /bin/bash
docker exec -it <container name> /bin/sh
docker exec -it <container name> ls

My question is, how do I docker exec a container that is built from scratch and consisting only of binaries? By doing a docker exec, I wish to find out if the files have been successfully copied from my host to the container (I have a COPY in the Dockerfile).

like image 277
P.K. Avatar asked Feb 16 '19 07:02

P.K.


People also ask

How do I execute a docker container?

To use the docker exec command, you will need a running Docker container. If you don't already have a container, start a test container with the following docker run command: docker run -d --name container-name alpine watch "date >> /var/log/date. log"

How do I Dockerize an existing project?

Use the "Dockerized" project Use a database client on your host OS to connect to the exposed db port on localhost:3306. Save the dump to db-backups, then use docker-compose exec db /bin/bash to load the database using the command line.

How do I start an existing docker container?

To restart an existing container, we'll use the start command with the -a flag to attach to it and the -i flag to make it interactive, followed by either the container ID or name. Be sure to substitute the ID of your container in the command below: docker start -ai 11cc47339ee1.


3 Answers

If your scratch container is running you can copy a shell (and other needed utils) into its filesystem and then exec it. The shell would need to be a static binary. Busybox is a great choice here because it can double as so many other binaries.

Full example:

# Assumes scratch container is last launched one, else replace with container ID of
# scratch image, e.g. from `docker ps`, for example:
# scratch_container_id=401b31621b36
scratch_container_id=$(docker ps -ql)

docker run -d busybox:latest sleep 100
busybox_container_id=$(docker ps -ql)
docker cp "$busybox_container_id":/bin/busybox .

# The busybox binary will become whatever you name it (or the first arg you pass to it), for more info run:
# docker run busybox:latest /bin/busybox
# The `busybox --install` command copies the binary with different names into a directory.

docker cp ./busybox "$scratch_container_id":/busybox

docker exec -it "$scratch_container_id" /busybox sh -c '
export PATH="/busybin:$PATH"
/busybox mkdir /busybin
/busybox --install /busybin
sh'

For Kubernetes I think Ephemeral Containers provide or will provide equivalent functionality.

References: distroless java docker image error https://github.com/GoogleContainerTools/distroless/issues/168#issuecomment-371077961

like image 99
gib Avatar answered Oct 21 '22 12:10

gib


There are several options.

  1. You can do docker container cp ${CONTAINER}:/path/to/file/on/container /path/to/temp/dir/on/host. This will copy the files to your host where you can inspect things using host tools.
  2. You can add an appropriate VOLUME to your Dockerfile. Then you can docker container inspect ${CONTAINER}. This will expose the volume name where the files should be. You can then inspect those in another container (based off an image with all the tools you need).
  3. You can at runtime bind the container to a volume or host directory at the appropriate place.
  4. You can add those binaries that you feel you need to the image. If you need /bin/ls or /bin/sh, then you can add them.
  5. You can bind mount the necessary binaries to the container - so the container has them for verification purposes but the image is not bloated by them.
like image 21
emory Avatar answered Oct 21 '22 12:10

emory


You can only use docker exec to run commands that actually exist in a container. If those commands don't exist, you can't run them. As you've noted, the scratch base image contains nothing – no shells, no libraries, no system files, nothing.

If all you're trying to check is if a Dockerfile COPY command actually copied the files you said it would, I'd generally assume the tooling works and just reference the copied files in my application.

Since it sounds like you control the Dockerfile, one workaround could be to change the base image to something lightweight but non-empty, like FROM busybox. That would give you a minimal set of tools that you could work with without blowing up the image size too much.

like image 38
David Maze Avatar answered Oct 21 '22 13:10

David Maze