CLI: Pass command to docker-compose up - docker

I have a docker-compose.yml (simplified example):
version: "3.8"
services:
server:
image: node:lts-slim
container_name: example-container
hostname: example-server
ports:
- 4000:4000
working_dir: /server
volumes:
- ./someLocalDirectory:/server
command: node --watch index.js
I create/start the container with docker-compose up -d server
Problem:
I'd prefer to not have command: node --watch index.js hardcoded inside the yml file.
Question:
Is it possible to pass command: node --watch index.js as an argument to docker-compose up -d server on the command line?
Thanks in advance :)
Solution:
You can prepend key-value-pairs on the command-line and treat them like regular variables inside docker-compose:
key="node --watch index.js" docker-compose up -d server
version: "3.8"
services:
server:
# ... see example above
command: ${key}
(see https://stackoverflow.com/a/50991623/1054981)

You have three options:
run:
You can use docker-compose run to run commands against a service.
For example:
docker-compose run server node --watch index.js
Note: container stops when command exits.
See also: docs
exec:
You can use docker-compose exec to run commands in a running container.
To start and keep your server running:
services:
server:
[..]
command: tail -f /dev/null
Start service:
docker-compose up -d server
Run commands:
docker-compose exec server node --watch index.js
See also: docs
using an environment variable:
You can pass an env var to your docker-compose file that contains the command you want to run.
Pass an environment variable to server:
services:
server:
[..]
command: $COMMAND
Run service:
COMMAND="node --watch index.js" docker-compose up -d server
See also: docs

Related

Start a container in interactive shell in docker compose [duplicate]

Is there any way to start an interactive shell in a container using Docker Compose only? I've tried something like this, in my docker-compose.yml:
myapp:
image: alpine:latest
entrypoint: /bin/sh
When I start this container using docker-compose up it's exited immediately. Are there any flags I can add to the entrypoint command, or as an additional option to myapp, to start an interactive shell?
I know there are native docker command options to achieve this, just curious if it's possible using only Docker Compose, too.
You need to include the following lines in your docker-compose.yml:
version: "3"
services:
app:
image: app:1.2.3
stdin_open: true # docker run -i
tty: true # docker run -t
The first corresponds to -i in docker run and the second to -t.
The canonical way to get an interactive shell with docker-compose is to use:
docker-compose run --rm myapp
(With the service name myapp taken from your example. More general: it must be an existing service name in your docker-compose file, myapp is not just a command of your choice. Example: bash instead of myapp would not work here.)
You can set stdin_open: true, tty: true, however that won't actually give you a proper shell with up, because logs are being streamed from all the containers.
You can also use
docker exec -ti <container name> /bin/bash
to get a shell on a running container.
The official getting started example (https://docs.docker.com/compose/gettingstarted/) uses the following docker-compose.yml:
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
After you start this with docker-compose up, you can shell into either your redis container or your web container with:
docker-compose exec redis sh
docker-compose exec web sh
docker-compose run myapp sh should do the deal.
There is some confusion with up/run, but docker-compose run docs have great explanation: https://docs.docker.com/compose/reference/run
If anyone from the future also wanders up here:
docker-compose exec service_name sh
or
docker-compose exec service_name bash
or you can run single lines like
docker-compose exec service_name php -v
That is after you already have your containers up and running.
The service_name is defined in your docker-compose.yml file
Using docker-compose, I found the easiest way to do this is to do a docker ps -a (after starting my containers with docker-compose up) and get the ID of the container I want to have an interactive shell in (let's call it xyz123).
Then it's a simple matter to execute
docker exec -ti xyz123 /bin/bash
and voila, an interactive shell.
This question is very interesting for me because I have problems, when I run container after execution finishes immediately exit and I fixed with -it:
docker run -it -p 3000:3000 -v /app/node_modules -v $(pwd):/app <your_container_id>
And when I must automate it with docker compose:
version: '3'
services:
frontend:
stdin_open: true
tty: true
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- /app/node_modules
- .:/app
This makes the trick: stdin_open: true, tty: true
This is a project generated with create-react-app
Dockerfile.dev it looks this that:
FROM node:alpine
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start"]
Hope this example will help other to run a frontend(react in example) into docker container.
I prefer
docker-compose exec my_container_name bash
If the yml is called docker-compose.yml it can be launched with a simple $ docker-compose up. The corresponding attachment of a terminal can be simply (consider that the yml has specified a service called myservice):
$ docker-compose exec myservice sh
However, if you are using a different yml file name, such as docker-compose-mycompose.yml, it should be launched using $ docker-compose -f docker-compose-mycompose.yml up. To attach an interactive terminal you have to specify the yml file too, just like:
$ docker-compose -f docker-compose-mycompose.yml exec myservice sh
A addition to this old question, as I only had the case last time. The difference between sh and bash. So it can happen that for some bash doesn't work and only sh does.
So you can:
docker-compose exec CONTAINER_NAME sh
and in most cases: docker-compose exec CONTAINER_NAME bash
use.
If you have time. The difference between sh and bash is well explained here:
https://www.baeldung.com/linux/sh-vs-bash
You can do docker-compose exec SERVICE_NAME sh on the command line. The SERVICE_NAME is defined in your docker-compose.yml. For example,
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
The SERVICE_NAME would be "zookeeper".
According to documentation -> https://docs.docker.com/compose/reference/run/
You can use this docker-compose run --rm app bash
[app] is the name of your service in docker-compose.yml

Starting docker containers

I have a docker-compose.yml file that starts two services: amazon/dynamodb-local on 8000 port and django-service. django-service runs tests that are dependent on dynamodb-local.
Here is working docker-compose.yml:
version: '3.8'
services:
dynamodb-local:
image: "amazon/dynamodb-local:latest"
container_name: dynamodb-local
ports:
- "8000:8000"
django-service:
depends_on:
- dynamodb-local
image: django-service
build:
dockerfile: Dockerfile
context: .
env_file:
- envs/tests.env
volumes:
- ./:/app
command: sh -c 'cd /app && pytest tests/integration/ -vv'
Now I need to run this without docker-compose, only using docker itself. I try to do following:
docker network create -d bridge net // create a network for dynamodb-local and django-service
docker run --network=net --rm -p 8000:8000 -d amazon/dynamodb-local:latest // run cont. att. to network
docker run --network=net --rm --env-file ./envs/tests.env -v `pwd`:/app django-service /bin/sh -c 'env && cd /app && pytest tests/integration -vv'
I can see that both services start, but I can't connect to the dynamo-db.
Where is the problem? Any comment or help is appreciated!
Through the docker-compose.yml, the amazon/dynamodb-local container has a name defined (container_name: dynamodb-local, If we do not set this property, docker-compose will use the service's name as container name). This enables other containers in the same network to address the container through its name.
In the docker-run command, we do not set an explicit container name. We can set an explicit container name by executing docker run ... --name dynamodb-local .... More details can be found in the corresponding docker run documentation.

docker-compose up -d failed

I wrote a simple docker-compose.yml as bellow,
version: '3'
services:
ubuntu:
container_name: ubuntu
image: ubuntu
debian:
container_name: debian
image: debian
then ran
$ docker-compose up -d
finally I got two containers with exited status.
even I typed
$ docker start <container_id>
trying to make containers running, but still fail.
Anyone tell me how to fix my yaml file, to make this two containers run with 'docker-compose up -d' ?
The entrypoint and command for these 2 docker images ubuntu and debian will not do anything that keep the container running.
In case you want them to keep running, you can modify your docker-compose file like this
version: '3'
services:
ubuntu:
container_name: ubuntu
image: ubuntu
entrypoint:
- bash
- -c
command:
- |
tail -f /dev/null
debian:
container_name: debian
image: debian
entrypoint:
- bash
- -c
command:
- |
tail -f /dev/null

Launch a graphical application with docker-compose

I have a simple command to run a java file (power architect) application with graphical interface in a docker container.
sudo docker run --rm --net=host --env="DISPLAY" --name cont_sql_power_architect -it -v $HOME/Desktop/FRM_project/volumes/sql_power_architect:/project img_sql_power_architect java -jar project/architect-1.0.8/architect.jar &
I try to reproduce it in docker-compose
services:
sql_power_architect:
build:
context: ./dockerfiles/
dockerfile: dockerfile_sql_power_architect
image: img_sql_power_architect
container_name: cont_sql_power_architect
environment:
- DISPLAY
network_mode: "host"
stdin_open: true
tty: true
volumes:
- ./volumes/sql_power_architect:/project
command:
- java -jar project/architect-1.0.8/architect.jar &
When I launch the docker-compose up -d, the container is launched but instantaneously stopped. The commands seems to be the same than the docker run. I don't see what I am missing.
Any Idea ?
PS to be able to run with a docker run, I have to execute before the command xhost +"local:docker#" each time I open a new console. But I still execute it before the docker-compose command.

Launching docker command from docker-compose v.3 file

I'm learning about Docker and I'm at first steps.
I've to 'refresh' postgres image from compose file to initialize db scripts as YOSIFKIT here do through shell (https://github.com/docker-library/postgres/issues/193).
here is my Docker file:
FROM postgres:9.6.7
COPY docker-postgresql-9.6.7/prova.sql /docker-entrypoint-initdb.d/
and here is my compose file:
version: '3'
services:
postgresql_rdbms:
restart: always
image: postgres-prova
build:
context: ../
dockerfile: docker-postgresql-9.6.7/Dockerfile
command: bash -c "docker run -it --rm postgres-prova ls -ln /docker-entrypoint-initdb.d && docker run -it --rm postgres-prova && postgres"
environment:
PG_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- /srv/docker/postgresql:/var/lib/postgresql
HOW can I insert a command in a compose-file to do "docker run -it --rm imageToReload" ???
Because I've seen that "command:" in compose file works inside the container, but I want operate ON the container, on a upper level (=manage the container from the compose file, after the container creation)
Thank you very much
From what I understand you want docker-compose to delete/remove the container after every run so that the build is run each time and a fresh prova.sql file can be copied into the image each time the service is brought up. The --force-recreate flag is probably what you need.
The command directive within the yaml file provides the command that is run inside the container.

Resources