docker compose build single container - docker

Using Compose, if I run docker-compose build, it will rebuild all the containers :
> docker-compose build
Building elasticsearch
Step 1 : FROM elasticsearch:2.1
---> a05cc7ed3f32
Step 2 : RUN /usr/share/elasticsearch/bin/plugin install analysis-phonetic
---> Using cache
---> ec07bbdb8a18
Successfully built ec07bbdb8a18
Building search
Step 1 : FROM php:5.5.28-fpm
---> fcd24d1058c0
...
Even when rebuilding using cache, this takes time. So my question is:
Is there a way to rebuild only one specific container?

Yes, use the name of the service:
docker-compose build elasticsearch

docker-compose up -d --no-deps --build <service_name>
Source

if you want to run and recreate a specific service inside your docker-compose file you can do it the same way as #dnephin proposed, like
$ docker-compose up -d --force-recreate --no-deps --build service_name
Suppose your docker-compose.yml file is like
version: '3'
services:
service_1:
.....
service_2:
.....

You could added --no-start flag to docker-compose, and start later since you will only build one service.

Related

Docker compose stops multiple services

I hope I didn't miss anything simple from the manual.
The structure is:
/home/user
/foo1/bar1/docker/
Dockerfile
docker-compose.yml
/foo2/bar2/docker/
Dockerfile
docker-compose.yml
docker-compose.yml
version: '3.9'
services:
foo1-bar1:
build:
context: .
args:
DOCKER_SERVER_ROOT_DIR: ${DOCKER_SERVER_ROOT_DIR}
dockerfile: Dockerfile
image: foo1-bar1:v1
container_name: foo1-bar1-v1
The same is for foo-bar-v2.
Both of them I successfully run as:
cd /foo1/bar1/docker/
docker-compose up -d
[+] Running 1/1
⠿ Container foo1-bar1-v1 Started
cd /foo2/bar2/docker/
docker-compose up -d
[+] Running 1/1
⠿ Container foo2-bar2-v1 Started
The question is, why does it stop both of them when I try to stop only 1? Service names, container names, image names are different...
user#vm:~/foo1/bar1/docker$ docker-compose stop
[+] Running 2/2
⠿ Container foo1-bar1-v1 Stopped
⠿ Container foo2-bar2-v2 Stopped
docker-compose has the concept of projects. Run docker-compose --help and you will see:
--project-directory string Specify an alternate working directory
(default: the path of the, first specified, Compose file)
-p, --project-name string Project name
So in your case, both your services belong to the same project named docker.
You can actually run docker-compose -p docker ps and you will see both your services.
You can also override this by specifying your own project name independent of the directory name.
My version of docker-compose (Docker Compose version v2.10.2 MacOS) does warn me that there are orphan containers in this project when I replicate your setup. Also it doesn't automatically stop "orphan" services and gives a warning that the network could not be removed either.
This is also another interesting fact: both services run on the same network (docker_default) only because the project name (folder name) is the same.
I hope this explains it.
You have to specify the service to stop. Otherwise it will stop all services.
docker compose stop [OPTIONS] [SERVICE...]
here : docker-compose stop foo1-bar1

Docker Compose: Change COMPOSE_PROJECT_NAME without rebuilding the application

Summary:
I have an application X, I want to deploy multiple instances of the same application (port numbers will be handled by an .env) in the same OS without starting a build for each instance.
What I tried:
So I managed to dynamically (by the user changing .env file), change the container_name of a container. But then we cannot run 5 instances at the same time (even if the ports are different, docker just stops the first re-creates the container for second)
Next I came across COMPOSE_PROJECT_NAME that seems to work BUT starts a new build.
COMPOSE_PROJECT_NAME=hello-01
docker-compose up
Creating network "hello-01_default" with the default driver
Building test
Step 1/2 : FROM ubuntu:latest
---> 113a43faa138
Step 2/2 : RUN echo Hello
---> Using cache
---> ba846acc19e5
Successfully built ba846acc19e5
Successfully tagged hello-01_test:latest
WARNING: Image for service test was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating hello-01_test ... done
Attaching to hello-01_test
hello-01_test exited with code 0
COMPOSE_PROJECT_NAME=hello-2
docker-compose up
Creating network "hello-02_default" with the default driver
Building test
Step 1/2 : FROM ubuntu:latest
---> 113a43faa138
Step 2/2 : RUN echo Hello
---> Using cache
---> ba846acc19e5
Successfully built ba846acc19e5
Successfully tagged hello-02_test:latest
WARNING: Image for service test was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating hello-02_test ... done
Attaching to hello-02_test
hello-02_test exited with code 0
Source files
docker-compose.yml
version: '3'
services:
test:
container_name: "${COMPOSE_PROJECT_NAME}_test"
build: .
.env
COMPOSE_PROJECT_NAME=hello-02
Dockerfile
FROM ubuntu:latest
RUN echo Hello
Ubuntu 18.04.1 LTS
Docker version 18.06.0-ce, build 0ffa825
docker-compose version 1.21.2, build a133471
By changing the container name without providing an image: reference the compose file has no idea that you've already built that image. So if you build that docker image as some local image example/image/local, you can addimage: example/image/localto your docker-compose file and do that to spawndocker-compose up -d` many times by changing the name with an environment variable in your example.
However, it appears that you might want to look into using replicas instead of making this a horrifically manual effort outside of on the one-line full up that you'd get out of docker-compose.
https://docs.docker.com/compose/compose-file/#short-syntax

docker-compose insert an extra command upon container creation

I have a docker-compose project where each service has its own command to run upon startup.
I want to add an extra command before the one given in the docker-compose.yml that will execute only when the container is first created.
Since I'm not sure this is possible, it is also acceptable for me to manually run commands before calling docker-compose up.
Given the following docker-compose.yml
version: '2.3'
version: '2.3'
services:
serv1:
image: my_image
command: some startup command
serv2:
image: my_image
command: some startup command 2
I have tried to run the following
$ docker-compose run serv1 my_creation_command
$ docker-compose run serv2 my_creation_command
$ docker-compose up
But this results in the first two commands creating containers projectname_serv1_run_1 and projectname_serv2_run_1 and the third command creating projectname_serv1_1 and projectname_serv2_1
This is obviously a problem since the my_creation_command never ran on the containers created by the up command
Any solution that will manage to get a custom command executed only on the creation part will be acceptable
A possible and easy solution is to wrap init command and run command into a unique script (let's call it init_or_run) :
version: '2.3'
services:
serv1:
image: my_image
command: init_and_run
serv2:
image: my_image
command: init_and_run_2
These scripts have to handle init and run cases. I've already done that for databases (see example below).
Example (with a database)
in init_and_run's init case, creates database/tables
in init_and_run's run case, just starts the database daemon
Checking if you have to run init part of the script here could be just verifying if database exist :
if database_does_not_exist
then
create_database_and_tables # init case
fi
run_database_daemon # in both cases, run database daemon
With this solution, you just have to run docker-compose up to start your services, without caring if service have already been initialized, because init_and_run script will handle both cases (init and run or just run).

Why does docker-compose depends on working directory?

When calling docker-compose in different directories, I get conflict errors and problems with networking:
Problem with conflicts
docker-compose.yml
version: '3'
services:
redis:
image: "redis:alpine"
container_name: redis
I. create and start docker container by docker-compose => OK
$ docker-compose up --force-recreate -d
Creating redis ... done
II. recreate and start docker container by docker-compose => OK
$ docker-compose up --force-recreate -d
Recreating redis ... done
III. copy docker-compose.yml to other directory.
Then try to recreate from other directory => ERROR
$ cp docker-compose.yml red2/
$ cd red2/
$ docker-compose up --force-recreate -d
Creating redis ... error
ERROR: for redis Cannot create container for service redis: Conflict. The container name "/redis" is already in use by container "1ba060b545f716731ac1c5992b680e4d4b3639fc0ffeb291899c712f0839d23a". You have to remove (or rename) that container to be able to reuse that name.
ERROR: Encountered errors while bringing up the project.
Different Networks
Containers created from docker-compose in different directories also do not share the same network.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
4a4af52e89cd red2_default bridge local
57695428bd9d redis_default bridge local
Usecase
My usecase for that szenario:
Call docker-compose from different deployment jobs.
Start containers for testing
Questions
Why is there the directory dependency? Is there an option to switch it off?
Does docker ps show which directory was used?
Answer for 1:
The directory name is used as the default project name.
You should better specify the project name:
docker-compose -p myproject up --force-recreate -d
Question 2 still open

Docker compose couldn't run static html pages

I have developed some static web-pages using jQuery & bootstrap.Here follows the folder structure,
Using below command i can able to run the docker image
Build the image
docker build -t weather-ui:1.0.0 .
Run the docker image
docker run -it -p 9080:80 weather-ui:1.0.0
Which is working fine and i can able to see the pages using http://docker-host:9080
But i would like to create a docker-compose for it,I have created a docker-compose file like below
version: '2'
services:
weather-ui:
build: .
image: weather-ui:1.0.0
volumes:
- .:/app
ports:
- "9080:9080"
The above compose file was not working and it stuck,
$docker-compose up
Building weather-ui
Step 1 : FROM nginx:1.11-alpine
---> bedece1f06cc
Step 2 : MAINTAINER ***
---> Using cache
---> ef75a70d43e8
Step 3 : COPY . /usr/share/nginx/html
---> 6fbc3a1d4aff
Removing intermediate container 2dc46f1f751d
Successfully built 6fbc3a1d4aff
WARNING: Image for service weather-ui was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Recreating weatherui_weather-ui_1 ...
Recreating weatherui_weather-ui_1 ... done
Attaching to weatherui_weather-ui_1
It stuck in the above line and i really don't know why it stuck?
Any pointers or hint would be great to resolve this issue.
As per Antonio edit,
I can see the running container,
$docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69ea4ff1a3ea weather-ui:1.0.2 "nginx -g 'daemon ..." 6 seconds ago Up 5 seconds 80/tcp, 443/tcp, 0.0.0.0:9080->9080/tcp weatherui_weather-ui_1
But while launching the page i couldn't see anything.It says the site can't be reached
docker-compose up build your docker container (if not already done) and attach the container to your console.
If you open your browser, and go to http://localhost:9080, you should see your website.
You don't need to map a volume : volumes: - .:/app in docker-compose.yml because you already copy static files in Dockerfile :
COPY . /usr/share/nginx/html
If you want to launch your container in the background (or in "detached" mode), add -d option : docker-compose up -d.
And by default docker-compose to not "rebuild" container if already exists, to build new container each time, add --build option : docker-compose up -d --build.

Resources