How to run a bash script from a Dockerfile on a Mac - bash

I'm trying to run a bash script from a Docker Image on a Mac. Here is my Dockerfile
FROM bash
ADD app.sh /
ENTRYPOINT ["/bin/bash", "/app.sh"]
Error
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.
This is a simple exercise in creating Docker Images where I need to execute app.sh when I run docker run.
Any idea what I'm doing wrong?

According to your error message, the file /bin/bash does not exist in your Docker image. Why is this?
The bash image puts the bash executable at /usr/local/bin/bash. Here's how I determined this:
$ docker run -it bash
bash-5.1# which bash
/usr/local/bin/bash
bash-5.1#
I ran the bash image with -it to make it interactive, then used the which command to give me the full path to bash, which is /usr/local/bin/bash.
For that reason, you need to change your Dockerfile like this:
FROM bash
ADD app.sh /
ENTRYPOINT ["/usr/local/bin/bash", "/app.sh"]

Related

Command Not Found with Dockerfile CMD

I have a Dockerfile that uses
CMD ['/usr/local/bin/gunicorn', '-b 0.0.0.0:8000', 'myapp.wsgi']
But when I run the container using docker run --rm myimage:latest I get an error:
/bin/sh: 1: [/usr/local/bin/gunicorn,: not found
Yet, when I run docker run --rm -it myimage:latest /bin/bash to go into the container, I can see that gunicorn runs, and running which gunicorn returns the correct path for gunicorn. Why is it failing to run?
Similarly, I planned on adding
ENTRYPOINT ['/entrypoint.sh']
to my Dockerfile, but when I run that, I get the error
/bin/sh: 1: /bin/sh: [/entrypoint.sh]: not found
The entrypoint.sh file contains:
#! /bin/bash
echo 'Starting app...'
cd /app || exit;
python manage.py migrate;
So why does it keep saying command not found when all the commands are there?
The issue here is the quotes. Use double " quotes.
From Docker Documentation:
The exec form is parsed as a JSON array, which means that you must use
double-quotes (“) around words not single-quotes (‘).
This is applicable for other instructions such as RUN, LABEL, ENV, ENTRYPOINT and VOLUME.

/bin/sh: No such file or directory when setting a docker-compose entrypoint

I have a container that runs a database migration (source):
FROM golang:1.12-alpine3.10 AS downloader
ARG VERSION
RUN apk add --no-cache git gcc musl-dev
WORKDIR /go/src/github.com/golang-migrate/migrate
COPY . ./
ENV GO111MODULE=on
ENV DATABASES="postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver firebird"
ENV SOURCES="file go_bindata github github_ee aws_s3 google_cloud_storage godoc_vfs gitlab"
RUN go build -a -o build/migrate.linux-386 -ldflags="-s -w -X main.Version=${VERSION}" -tags "$DATABASES $SOURCES" ./cmd/migrate
FROM alpine:3.10
RUN apk add --no-cache ca-certificates
COPY --from=downloader /go/src/github.com/golang-migrate/migrate/build/migrate.linux-386 /migrate
ENTRYPOINT ["/migrate"]
CMD ["--help"]
I want to integrate it into a docker-compose and make it dependent on the Postgres database service. However, since I have to wait until the database is fully initialised I have to wrap the migrate command in a script and thus replace the entrypoint of the migration container. I'm using the wait-for script to poll the database, which is a pure shell (not bash) script and should thus work in an alpine container.
This is how the service is defined in the docker-compose:
services:
database:
# ...
migration:
depends_on:
- database
image: migrate/migrate:v4.7.0
volumes:
- ./scripts/migrations:/migrations
- ./scripts/wait-for:/wait-for
entrypoint: ["/bin/sh"]
command: ["./wait-for database:5432", "--", "./migrate", "-path", "/migrations", "-database", "postgres://test:test#database:5432/test?sslmode=disable", "-verbose", "up"]
Running docker-compose up on this fails with
migration_1 | /bin/sh: can't open './wait-for database:5432': No such file or directory
Running the migrate container for itself with
docker run -it --entrypoint /bin/sh -v $(pwd)/scripts/wait-for:/wait-for migrate/migrate:v4.7.0
does work flawlessly, the script is there and can be run with /bin/sh ./wait-for.
So why does it fail as part of the docker-compose?
If you read the error message carefully, you will see that the file that cannot be found is not ./waitfor, it is ./wait-for database:5432. This is consistent with your input file, where that whole thing is given as the first element of the command list:
command: ["./wait-for database:5432", "--", "./migrate", "-path", "/migrations", "-database", "postgres://test:test#database:5432/test?sslmode=disable", "-verbose", "up"]
It's unclear to me what you actually want instead, since the working alternatives presented do not seem to be fully analogous, but possibly it's
command: ["./wait-for", "database:5432", "--", "./migrate", "-path", "/migrations", "-database", "postgres://test:test#database:5432/test?sslmode=disable", "-verbose", "up"]
Running the migrate container for itself with does work flawlessly
When you run it like:
docker run -it --entrypoint /bin/sh -v $(pwd)/scripts/wait-for:/wait-for migrate/migrate:v4.7.0
entrypoint /bin/sh is executed.
When you run it using docker-compose:
entrypoint (/bin/sh ) + command (./wait-for database:5432) ...` is executed.
./wait-for database:5432 as whole stands for executable that will run and it can't be found, that's why you get the error No such file or directory
Try to specify an absolute path to wait-for in command: and split ./wait-for database:5432 into "./wait-for", "database:5432".
It's possible that splitting will be enough
As an alternative you can follow CMD syntax docs and use different command syntax without array: command: ./wait-for database:5432 ...
ENTRYPOINT ["/bin/sh"] is not enough, you also need the -c argument.
Example (testing a docker-compose.yml with docker-compose run --rm MYSERVICENAMEFROMTHEDOCKERCOMPOSEFILE bash here):
entrypoint: ["/bin/sh"]
Throws:
/bin/sh: 0: cannot open bash: No such file
ERROR: 2
And some wrong syntax examples like
entrypoint: ["/bin/sh -c"]
(wrong!)
or
entrypoint: ["/bin/sh, -c"]
(wrong!)
throw errors:
starting container process caused: exec: "/bin/sh, -c": stat /bin/sh, -c: no such file or directory: unknown
ERROR: 1
starting container process caused: exec: "/bin/sh -c": stat /bin/sh -c: no such file or directory: unknown
ERROR: 1
In docker-compose or Dockerfile, for an entrypoint, you need the -c argument.
This is right:
entrypoint: "/bin/sh -c"
or:
entrypoint: ["/bin/sh", "-c"]
The -c is to make clear that this is a command executed in the command line, waiting for an additional command to be used in that command line. but not starting the bash /bin/sh just on its own. You can read that between the lines at What is the difference between CMD and ENTRYPOINT in a Dockerfile?.

Execute script when docker container start

I want container with "centos:latest" image to be started and should execute my script. The scripts are copied with docker cp commands.
docker create --name centos1 centos:latest
docker cp . 5db38b908880:/opt ---> scripts are in current directory, hence .
docker commit centos1 new_centos1 --> now new_centos1 image has scripts
Now I want to start new container with the scripts to be executed: I tried below commands:
docker run -ti --rm --entrypoint "cd /opt && deploy_mediainfo_lambda.sh" new_centos1:latest
docker run -ti --rm new_centos1:latest "cd /opt && deploy_mediainfo_lambda.sh"
Both of above commands failed with:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:296: starting container process caused "exec: \"cd /opt && deploy_mediainfo_lambda.sh\": stat cd /opt && deploy_mediainfo_lambda.sh: no such file or directory": unknown.
ERRO[0000] error waiting for container: context canceled
if used bash command while starting container, I can run my script using 'execuateble path'/'execuatble name' inside container, but I can not do this while starting container on commandline
docker run -ti --rm new_centos1:latest bash
[root#c34207f3f1c4 /]# ./opt/deploy_mediainfo_lambda.sh
If used below command, which calls executable directly, it gives path error.
docker run -ti --rm new_centos1:latest "deploy_mediainfo_lambda.sh"
docker: Error response from daemon: OCI runtime create failed: container_linux.go:296: starting container process caused "exec: \"deploy_mediainfo_lambda.sh\": executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled
Also not sure about setting $PATH from commandline while starting the container.
I know, using Dockerfile this is achievable, like:
can set path using ENV,
can copy executables with ADD or COPY
run executables using CMD or ENTRYPOINT
How to achieves it using docker commandline?
Thanks melpomene.
Here is my bash script to automate script execution inside container, after copying them, all using docker commands.
# Start docker container
docker create --name mediainfo_docker centos:latest
# copy script files
docker cp . mediainfo_docker:/opt
# save container with the new image, which contains all scripts.
docker commit mediainfo_docker mediainfo_docker_with_scripts
# Now run scripts inside docker container
docker run -ti --rm mediainfo_docker_with_scripts:latest /opt/deploy_mediainfo_lambda.sh
Since deploy_mediainfo_lambda.sh is a script, first line of it is:
#!/bin/bash

Running shell script using Docker image

Input:
- There is Windows machine with Docker Toolbox installed.
- There is a shell script file baz.sh which calls py2dsc-deb.
Problem: py2dsc-deb is not available on Windows.
As I understand correctly, I can pull some Linux distro image from Docker repository, create a container and then execute shell-script file and it will run py2dsc-deb and do its job.
I have pulled:
debian - stretch-slim - 3ad21 - 3 weeks ago - 55.3MB
Now
How do I run my script using debian, something like: docker exec mycontainer /path/to/test.sh?
Running docker --rm debian:stretch-slim does nothing. Doesn't it suppose to run Debian distro at docker-machine ip?
I have tried to keep the container up using docker run -it debian:stretch-slim /bin/bash, then run the script using docker exec 1ef5b ./build.sh, but getting
$ docker exec 745 ./build.sh
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"./build.sh\": stat ./build.sh: no such file or directory"
Does it mean I can't run external script and has to always pass it inside the Docker?
You can execute bash command inside your container by typing
docker exec -ti -u `username` `container_name` bash -c "cd /path/to/ && ./test.sh"
lets say your container name is test_buildbox, you are root and your script stays inside /bin/test.sh You can call this script by typing
docker exec -ti -u root test_buildbox bash -c "cd /bin/ && ./test.sh
Please check if you have correct line endings in your .sh scripts (<LF>) when you built Docker image on Windows.

Can't change directories in a docker container?

I am attempting to run a few commands inside of a docker container from it's host machine. Typically when I want to execute a shell command in a docker container from the host I will do something like this:
docker exec -ti myContainer ls -l
which works fine. But when I try to change directories like this:
docker exec -ti myContainer cd myDirectory
it throws the error:
rpc error: code = 2 desc = "oci runtime error: exec failed: exec:
\"cd\": executable file not found in $PATH"
Does anyone have any idea why this would be happening and how I can resolve it?
cd isn't an OS executable, is a shell command. To run it, you'll need to run a shell to parse it. docker exec -ti myContainer /bin/sh -c "cd myDirectory"

Resources