I need to have the hostname of the host in order to run entrypoint script, that runs accordingly (production, preproduction). How can I get the hostname and to set it as ARG inside Dockerfile. This docker file is used by docker-compose.yml.
docker-compose.yml:
...
nginx:
restart: always
build: ./nginx
ports:
- "80:80"
- "443:443"
volumes_from:
- web
depends_on:
- web
container_name: 'nginx'
...
Dockerfile inside ./nginx folder:
FROM nginx:latest
ARG HOST_HOSTNAME=hostname
ENV HOST_HOSTNAME=$HOST_HOSTNAME
COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
...
And inside docker-entrypoint.sh to be able to use ${HOST_HOSTNAME}. Also I want this code to be able to run on every machine without changing anything, but just adding new hostnames to docker-entrypoint.sh
You should pass hostname though environment variable
Related
i'm using Docker-Desktop on Windows and i'm trying to get running 3 containers inside docker-desktop.
After few research and test, i get the 3 container running [WEB - API - DB], everything seems to compile/run without issue in the logs but i'can't access my web container from outside.
Here's my dockerfile and docker-compose, what did i miss or get wrong ?
[WEB] dockerfile
FROM node:16.17.0-bullseye-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
CMD ["npm", "run", "start"]
[API] dockerfile
FROM openjdk:17.0.1-jdk-slim
WORKDIR /app
COPY ./target/test-0.0.1-SNAPSHOT.jar /app
#EXPOSE 2022 (the issue is the same with or without this line)
CMD ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
Docker-compose file
version: "3.8"
services:
### FRONTEND ###
web:
container_name: wallet-web
restart: always
build: ./frontend
ports:
- "80:4200"
depends_on:
- "api"
networks:
customnetwork:
ipv4_address: 172.20.0.12
#networks:
# - "api"
# - "web"
### BACKEND ###
api:
container_name: wallet-api
restart: always
build: ./backend
ports:
- "2022:2022"
depends_on:
- "db"
networks:
customnetwork:
ipv4_address: 172.20.0.11
#networks:
# - "api"
# - "web"
### DATABASE ###
db:
container_name: wallet-db
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
customnetwork:
ipv4_address: 172.20.0.10
#networks:
# - "api"
# - "web"
networks:
customnetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# api:
# web:
Listening on:
enter image description here
I found several issue similar to mine but the solution didn't worked for me.
If i understand you are trying to access on port 80. To do that, you have to map your container port 4200 to 80 in yaml file 80:4200 instead of 4200:4200.
https://docs.docker.com/config/containers/container-networking/
Have you looked in the browsers development console, if there comes any error. Your docker-compose seems not to have any issue.
How ever lets try to debug it:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6245eaffd67e nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:4200->80/tcp test-api-1
copy the container id then execute:
docker exec -it 6245eaffd67e bin/bash
Now you are inside the container. Instead of the id you can use also the containers name.
curl http://localhost:80
Note: in my case here i just create a container from an nginx image.
In your case use the port where your app is running. Control it in your code if you arent sure. A lot of Javascript-frameworks start default on 3000.
If you get an error: curl command not found, install it in your image:
FROM node:16.17.0-bullseye-slim
USER root # to install dependencies you need sudo permissions su we tell the image that it is root
RUN apt update -y && apt install curl -y
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
USER node # we dont want to execute the image as root so we put user node (this user is defined in the node:16.17.0-bullseye-slim image)
CMD ["npm", "run", "start"]
Now the curl should work (if it doesnt already).
The same should work from your host.
Here is an important thing:
The localhost, always refers to the fisical computer, or the container itselfs where you are refering. Every container and your PC have localhost and they are not the same.
In the docker-compose you just map the port host/container, so your PC (host) where docker is running can access the docker network from the host on the host port you defined, inside the port of the container.
If you cant still access from your host, try to change the host ports 2022, 4200 ecc. Could be possible that something conflicts on your Windows machine.
It happens sometimes that the docker networks can create some conflicts.
Execute a docker-compose down, so it should be delete and recreated.
Still not working?
Reset docker-desktop to factory settings, control if you have last version (this is always better).
If all this doesnt help, let me know so we can debugg further.
For the sake of clarity i post you here the docker-compose which i used to check. I just used nginx to test the ports as i dont have your images.
version: "3.8"
services:
### FRONTEND ###
web:
restart: always
image: nginx
ports:
- "4200:80"
depends_on:
- "api"
networks:
- "web"
### BACKEND ###
api:
restart: always
image: nginx
ports:
- "2022:80"
depends_on:
- "db"
networks:
- "api"
- "web"
### DATABASE ###
db:
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
- "api"
networks:
api:
web:
```
Update:
You can log what happens in the conatiner like so:
```
docker logs containerid/name
```
If you are using Visualcode there is excellent extension for docker build also by Microsoft:
Just search docker in the extensions. Has something like 20.000.000 downloads and can help you a lot debugging containers ecc. After installing it you see the dockericon on the left toolbar.
If you can see directly the errors that occurs in the logs, maybe you can post them partially. So it would be possible to understand. Please tell also something about your Frontendapp architecture, (react-app, angular). There are some frameworks that need to be startet on 0.0.0.0 instead of 127.0.0.1 or they dont work.
I created a docker-compose file to build image from dockerfile and then run container this is my code:
Dockerfile
FROM anapsix/alpine-java
VOLUME [ "/var/run/jars/" ]
ADD hello-world.jar /var/run/jars/
EXPOSE 8080
ENTRYPOINT [ "java" ]
CMD ["-?"]
docker-compose.yml
version: '3'
services:
hello-world-image:
build: .
image: hello-world-image
hello-world:
image: hello-world-image
container_name: hello-world
ports:
- "8080:8080"
volumes:
- ./logs_ACM:/root/logs_ACM
command: -jar /var/run/jars/hello-world.jar
restart: always
docker ps output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
103b0a3c30e3 hello-world-image "java -jar /var/run/…" 5 seconds ago Restarting (1) Less than a second ago hello-world
When i check running containers with "docker ps" the port column is empty therefore no port mapping was done even though i specified ports in my docker compose file.
What changes needed to be done on my docker-compose file to solve this issue ?
new version of dockerfile and docker-compose :
FROM anapsix/alpine-java
USER root
RUN mkdir -p /var/run/jars/
COPY spring-petclinic-2.4.2.jar /var/run/jars/
EXPOSE 8081
ENTRYPOINT [ "java" ]
CMD ["-?"]
version: '3' # '3' means '3.0'
services:
spring-petclinic:
build: .
# Only if you're planning to `docker-compose push`
# image: registry.example.com/name/hello-world-image:${TAG:-latest}
ports:
- "8081:8081"
volumes:
# A bind-mount directory to read out log files is a good use of
# `volumes:`. This does not require special setup in the Dockerfile.
- ./logs_ACM:/root/logs_ACM
command: -jar /var/run/jars/spring-petclinic-2.4.2.jar
mysql:
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_ALLOW_EMPTY_PASSWORD=true
- MYSQL_USER=petclinic
- MYSQL_PASSWORD=petclinic
- MYSQL_DATABASE=petclinic
volumes:
- "./conf.d:/etc/mysql/conf.d:ro"
I think your single biggest problem here is the VOLUME directive in the Dockerfile. The Dockerfile documentation for VOLUME notes:
Changing the volume from within the Dockerfile: If any build steps change the data within the volume after it has been declared, those changes will be discarded.
So when you declare a VOLUME for the directory containing the jar file, and then try to ADD content to it, it gets lost.
In most practical cases you don't need a VOLUME. You should be able to rewrite the Dockerfile to:
FROM anapsix/alpine-java
# Do not create a VOLUME.
# Generally prefer COPY to ADD. Will create the target directory if needed.
COPY hello-world.jar /var/run/jars/
EXPOSE 8080
# Don't set an ENTRYPOINT just naming an interpreter.
# Do make the default container command be to run the application.
CMD ["java", "-jar", "/var/run/jars/hello-world.jar"]
In the docker-compose.yml file, you don't need a separate "service" just to build the image, and you shouldn't typically need to override container_name: (provided by Compose) or command: (from the Dockerfile). This could be reduced to:
version: '3.8' # '3' means '3.0'
services:
hello-world:
build: .
# Only if you're planning to `docker-compose push`
# image: registry.example.com/name/hello-world-image:${TAG:-latest}
ports:
- "8080:8080"
volumes:
# A bind-mount directory to read out log files is a good use of
# `volumes:`. This does not require special setup in the Dockerfile.
- ./logs_ACM:/root/logs_ACM
# Don't enable auto-restart until you've debugged the start sequence
# restart: always
I'm unable to start Tomcat server from docker compose.
When I log into container using docker exec -it <container id> bash and see ps -eaf | grep "tomcat" it is showing empty. Tomcat server is not running.
docker-compose.yml file:
version: "3"
services:
meghcore:
build: ./Core
container_name: 'meghcore'
expose:
- '8080'
ports:
- '8080:8080'
volumes:
- meghcore:/opt/Tomcat1/webapps/
command: /bin/bash
tty: true
stdin_open: true
networks:
- meghnet
volumes:
meghcore:
networks:
meghnet:
driver: bridge
Dockerfile file:
FROM tomcat:8.5.35
WORKDIR /app
COPY . /app
RUN mv /app/*.war /opt/Tomcat1/webapps/
ENV PATH $PATH:/opt/Tomcat1/bin
WORKDIR /opt/Tomcat1/bin
EXPOSE 8080
CMD ["catalina.sh", "run"]
Since you specify an alternate command: in your docker-compose.yml file, that overrides the CMD in the Dockerfile. You don't need most of the options you specify there at all, and several of them (the alternate command:, the volumes: overwriting the actual application) interfere with the normal container operation.
A complete, functional docker-compose.yml would be
version: "3"
services:
meghcore:
build: ./Core
ports:
- '8080:8080'
None of the other options you list out are necessary. If there were other containers listed in the file, they could still communicate using their Docker Compose service names, without any special setup (another container in this same file could successfully call http://meghcore:8080).
What is happening is command specify in docker-compose.yml is overwriting the CMD provided in dockerfile.
kindly update command with the command available in dockerfile or remove command from docker-compose.yml
Problem is resolved by adding below commands in dockerfile and removed command from docker compose file.
ENV PATH $PATH:$JAVA_HOME/bin
ENV PATH $PATH:/opt/Tomcat1/bin
WORKDIR /opt/Tomcat1/bin
EXPOSE 8080
CMD ["catalina.sh", "run"]
I am using Docker which is running fine.
I can start a Docker image using docker-compose.
docker-compose rm nodejs; docker-compose rm db; docker-compose up --build
I attached a shell to the Docker container using
docker exec -it nodejs_nodejs_1 bash
I can view files inside the container
(inside container)
cat server.js
Now when I edit the server.js file inside the host, I would like the file inside the container to change without having to restart Docker.
I have tried to add volumes to the docker-compose.yml file or to the Dockerfile, but somehow I cannot get it to work.
(Dockerfile, not working)
FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
VOLUMES ["/usr/src/app"]
EXPOSE 8080
CMD [ "npm", "run", "watch" ]
or
(docker-compose.yml, not working)
version: "3.3"
services:
nodejs:
build: ./nodejs-server
ports:
- "8001:8080"
links:
- db:db
env_file:
- ./.env-example
volumes:
- src: /usr/src/app
db:
build: ./mysql-server
volumes:
- ./mysql-server/data:/docker-entrypoint-initdb.d #A folder /mysql-server/data with a .sql file needs to exist
env_file:
- ./.env-example
volumes:
src:
There is probably a simple guide somewhere, but I havn't found it yet.
If you want a copy of the files to be visible in the container, use a bind mount volume (aka host volume) instead of a named volume.
Assuming your docker-compose.yml file is in the root directory of the location that you want in /usr/src/app, then you can change your docker-compose.yml as follows:
version: "3.3"
services:
nodejs:
build: ./nodejs-server
ports:
- "8001:8080"
links:
- db:db
env_file:
- ./.env-example
volumes:
- .:/usr/src/app
db:
build: ./mysql-server
volumes:
- ./mysql-server/data:/docker-entrypoint-initdb.d #A folder /mysql-server/data with a .sql file needs to exist
env_file:
- ./.env-example
This is my basic NGINX setup that works!
web:
image: nginx
volumes:
- ./nginx:/etc/nginx/conf.d
....
I replace the volumes by copying ./nginx to /etc/nginx/conf.d using COPY ./nginx /etc/nginx/conf.d into my container. The issue was because, by using value the nginx.conf refer to log file in my host instead of my container. So, I thought by hardcopying the config file to container it will solve my problem.
However, NGINX is not running at all at docker compose up. What is wrong?
EDIT:
Dockerfile
FROM python:3-onbuild
COPY ./ /app
COPY ./nginx /etc/nginx/conf.d
RUN chmod +x /app/start_celerybeat.sh
RUN chmod +x /app/start_celeryd.sh
RUN chmod +x /app/start_web.sh
RUN pip install -r /app/requirements.txt
RUN python /app/manage.py collectstatic --noinput
RUN /app/automation/rm.sh
docker-compose.yml
version: "3"
services:
nginx:
image: nginx:latest
container_name: nginx_airport
ports:
- "8080:8080"
rabbit:
image: rabbitmq:latest
environment:
- RABBITMQ_DEFAULT_USER=admin
- RABBITMQ_DEFAULT_PASS=asdasdasd
ports:
- "5672:5672"
- "15672:15672"
web:
build:
context: ./
dockerfile: Dockerfile
command: /app/start_web.sh
container_name: django_airport
expose:
- "8080"
links:
- rabbit
celerybeat:
build: ./
command: /app/start_celerybeat.sh
depends_on:
- web
links:
- rabbit
celeryd:
build: ./
command: /app/start_celeryd.sh
depends_on:
- web
links:
- rabbit
This is your initial setup that works:
web:
image: nginx
volumes:
- ./nginx:/etc/nginx/conf.d
Here you have a bind volume that proxy, inside your container, all file system requests at /etc/nginx/conf.d to your host ./nginx. So there is no copy, just a bind.
This means that if you change a file in your ./nginx folder, you container will see the updated file in real time.
Load the configuration from the host
In your last setup just add a volume in the nginx service.
You can also remove the COPY ./nginx /etc/nginx/conf.d line in you web service Dockerfile, because it's useless.
Bundle configuration inside the image
Instead, if you want to bundle your nginx configuration inside a nginx image you should build a custom nginx image. Create a Dockerfile.nginx file:
FROM nginx
COPY ./nginx /etc/nginx/conf.d
And then change your docker-compose:
version: "3"
services:
nginx:
build:
dockerfile: Dockerfile.nginx
container_name: nginx_airport
ports:
- "8080:8080"
# ...
Now your nginx container will have the configuration inside it and you don't need to use a volume.