Cannot reach container from another one - docker

I'm trying to call an API from a nodeJS container to another one, without success.
Here's my docker-compose:
version: '3'
services:
alaunt-server:
build:
context: ./
dockerfile: server/Dockerfile
image: alaunt-server
container_name: alauntServer
restart: unless-stopped
alaunt-proxy:
build:
context: ./
dockerfile: proxy/Dockerfile
image: alaunt-proxy
container_name: alauntProxy
ports:
- "5050:5050"
restart: unless-stopped
The Dockerfile from both the services are quite the same:
FROM node:16.19.0-alpine
WORKDIR /home/proxy/
COPY .env .
COPY ./proxy/package.json .
COPY ./proxy/yarn.lock .
COPY ./proxy/. .
RUN yarn
CMD ["yarn", "proxy"]
The server is running internally on a port env.SERVER_PORT.
What I'm trying to do is to have the proxy exposed that calls a not exposed backend (the server).
So I've setup a simple API as following:
axios.get(`http://0.0.0.0:${env.SERVER_PORT}`).then(data => {
res.status(200).send(data.data);
}).catch(er => {
console.log(er)
res.status(500).send(format(500, "error"));
});
But this give me the error ECONNREFUSED.
I suspect this has something to do with the 0.0.0.0 but I've no clue.
What am I doing wrong?
EDIT:
I solved it. I just needed to create a network:
docker network create <your_name>.
And then I just referenced in the docker-compose for each service.
As always, thank you for the useless down vote, this community is getting worse and worse everytime.

Related

How to make docker-compose build faster

I have two services in my docker-compose.yaml that use the same build context:
service_1:
image: 'service_1:latest'
container_name: service_1
env_file:
- ./service_dir/.env
ports:
- "8000:80"
build:
context: ./service_dir/
dockerfile: Dockerfile
volumes:
- ./service_dir/app:/app
command: /start-reload.sh
service_2:
container_name: service_2
build:
context: ./service_dir/
dockerfile: Dockerfile
command: python app/my_script.py
Building this takes forever. I assume it has something to do with the fact that the build context is taken twice to the docker daemon? I'm not sure if these commands could be run in the same service but I'd prefer to have two separate containers so I can e.g. follow service_2 logs more easily. Any suggestions for a good solution to my problem?

Connection between docker containers: need to put gateway instead of name of container, why?

I was testing things for my own and I had problem: Trying to connect a nodeexpress container(app) to a mongo container(database), I can connect to mongo from MongoCompose if I connect to localhost:27017 but cant into the container of nodeexpress with mongoose configuration url to connect database like this 'mongodb://localhost:27017/dbtest'.
So I look up at SO some solutions (like this) and answers what I see was instead of 'mongodb://localhost:27017/dbtest' I need to write the name of the my container 'mongodb://mymongo:27017/dbtest', but for me this didnt work, only recieve ECONNREFUSED error.
Containers was in the same network, here is my dockerfile and docker-compose file.
Dockerfile
#node 8.16.2
FROM node:8.16.2
COPY . /app
WORKDIR /app
RUN npm install
EXPOSE 3000
CMD ["npm","start"]
docker-compose.yaml
version: "3.7"
services:
db:
image: mongo
ports:
- 27017:27017
networks:
- testing
app:
build:
context: .
dockerfile: Dockerfile
networks:
- testing
networks:
testing:
I solved this problem like this mongodb://172.17.0.1:27017/dbtest where 172.17.0.1 is the Gateway of the network that are the containers.
Can someone explain this behavior and if it is correct ?
Platform Linux
Where did you get the name mymongo from? You have defined the name of mongodb service as db in your compose file. So use the connection string 'mongodb://db:27017/dbtest'
version: "3.7"
services:
db: ---------------> This is the name of your mongo service
image: mongo
ports:
- 27017:27017
networks:
- testing
app:
build:
context: .
dockerfile: Dockerfile
networks:
- testing
networks:
testing:

Fail to obtain connection between two Docker containers

I have an application that is divided in 2 parts: Frontend and Backend. My Frontend is a React JS application and my backend is a Java Spring boot application. This project is running in Docker, and there's 3 containers: frontend, backend and db (database). My problem is that I can't make my front and send any request to my backend container. Below is my Docker configuration files:
Docker-compose:
version: "3"
services:
db:
image: postgres:9.6
container_name: db
ports:
- "5433:5432"
environment:
- POSTGRES_PASSWORD=123
- POSTGRES_USER=postgres
- POSTGRES_DB=test
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: backend
ports:
- "8085:8085"
depends_on:
- db
frontend:
container_name: frontend
build:
context: ./frontend
dockerfile: Dockerfile
expose:
- "80"
ports:
- "80:80"
links:
- backend
depends_on:
- backend
Dockerfile frontend:
# Stage 0, "build-stage", based on Node.js, to build and compile the frontend
FROM node:8.12.0 as build-stage
WORKDIR /app
COPY package*.json /app/
RUN yarn
COPY ./ /app/
RUN yarn run build
# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx
RUN rm -rf /usr/share/nginx/html/*
COPY --from=build-stage /app/build/ /usr/share/nginx/html
# Copy the default nginx.conf provided by tiangolo/node-frontend
COPY --from=build-stage /app/nginx.conf /etc/nginx/conf.d/default.conf
Dockerfile backend:
FROM openjdk:8
ADD /build/libs/reurb-sj-13-11-19.jar reurb-sj-13-11-19.jar
EXPOSE 8085
ENTRYPOINT ["java", "-jar", "reurb-sj-13-11-19.jar", "--app.db.host=
Is Frontend I've tried to send requests to these Ip's:
localhost:8085
172.18.0.3:8085
172.18.0.3
0.0.0.0:8085
When I try to send a request from Frontend, it "starts" and waits for about 10 seconds, then it returns with an error. The weird part is that my request doesn't return with any status.
PS.: I've read all internet and everyone said to put EXPOSE, PORTS and the LINKS (inside docker-compose), I've tried but still doesn't work.
You need to connect to backend:8085.
--
You shouldn't be using IP's to connect to your services but rather the service name listed in your docker-compose file.
Note: If using localhost, that refers to frontend container itself. Usually 0.0.0.0 is used to bind to all IP's or represent any IP address rather than connecting to a specific IP.
So in your front-end code, you need to use backend as the hostname (E.g., backend:8085).
It looks like you have already linked your services so networking shouldn't be an issue. My advice is to always test within the container using something such as:
docker-compose exec frontend bash
# You may need to install packages
ping backend
telnet backend 8085
I think it is worth mentioning that link is legacy and eventually will be removed.
Source: https://docs.docker.com/network/links/
Unless you really need it, you should create custom network for your app. Good documentation is here: https://docs.docker.com/compose/compose-file/#networks
And example:
version: "3"
services:
db:
image: postgres:9.6
container_name: db
ports:
- "5433:5432"
environment:
- POSTGRES_PASSWORD=123
- POSTGRES_USER=postgres
- POSTGRES_DB=test
networks:
- new
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: backend
ports:
- "8085:8085"
depends_on:
- db
networks:
- new
frontend:
container_name: frontend
build:
context: ./frontend
dockerfile: Dockerfile
expose:
- "80"
ports:
- "80:80"
networks:
- new
depends_on:
- backend
networks:
new:

golang program running fine outside of docker, but exiting with 0 when dockerized

I have the following docker-compose.yml file:
version: "3.3"
services:
api:
build: ./api
expose:
- '8080'
container_name: 'api'
ports:
- "8080:8080"
depends_on:
- db
stdin_open: true
tty: true
networks:
- api-net
db:
build: ./db
expose:
- '27017'
container_name: 'mongo'
ports:
- "27017:27017"
networks:
- api-net
networks:
api-net:
driver: bridge
and the Dockerfile for the api container is as follows:
FROM iron/go:dev
RUN mkdir /app
COPY src/main/main.go /app/
ENV SRC_DIR=/app
ADD . $SRC_DIR
RUN go get goji.io
RUN go get gopkg.in/mgo.v2
# RUN cd $SRC_DIR; go build -o main
CMD ["go", "run", "/app/main.go"]
If I run the code for main.go outside of a container it runs as expected, however if I try to run the container as part of docker-compose I get an exit 0. I have seen other threads on stackoverflow that have suggested using stdin_open and tty, but these have not helped. I have also tried creating an .env file in the same directory I issue docker-compose up from with COMPOSE_HTTP_TIMEOUT=8000 in it and this has not worked either. I am looking for helped and suggestions as to what I need to do in order for my api container to stay up.
I know that --verbose can be issued with docker-compose, however I'm not sure what I should be looking for in the output that this produces.
I finally managed to get to the bottom of this, in my code which worked outside of a container I had:
http.ListenAndServe("localhost:8080", mux)
the fix was to simply remove localhost such that I now have:
http.ListenAndServe(":8080", mux)

Docker - no access to other containers in the network during docker image build

I have two docker containers: simple rest api and a database. I want to start the rest api only when the database is ready. I tried several solutions, when i figured out the problem is in the network.
wait-for-it.sh script works perfectly fine when I start rest api without waiting for the database and then do docker exec -it <api-container-name> bash and run it from there. When I'm trying to run it as a CMD in Dockerfile it can't establish connection with the database. Same thing happens when I start the api while database is already running.
Api dockerfile:
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN chmod +x Scripts/wait-for-it.sh
RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306 #times out when waiting for database
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
docker-compose:
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
I see your confusion.
The RUN statement isn't doing what you think it is; it's running the wait-for-it.sh while the container is building, and isn't under the docker-compose's control. It will not run when your container runs! You should check out the documentation from docker about container start-up order and docker-compose.
Detached mode for your database will have no effect on build/run process; expect you won't be able to interact with it.
Using docker-compose will, by default, have all the container in non-interactive mode; but that's okay because you can still attach/detach to the containers.
You should add a depends-on option to your docker-compose.yml and add your wait-for-it.sh to the command option in the docker-compose.yml, not the Dockerfile.
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
# Add this `depends-on`
depends-on:
- "main-db"
# Add this `command` option
command: ["Scripts/wait-for-it.sh", "-t", "30", "172.20.1.2:3306"]
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
I would recommend moving wait-for-it.sh to your WORKDIR, and make sure it is passed as "./wait-for-it.sh" to command, just to make your life easier.
Don't forget to remove RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306 from your Dockerfile! (Because docker-compose is handling it now.)
And remember that the command for using docker-compose is docker-compose up, unless, that is, you'd like to use docker swarm instead.
Well. I managed to solve my problem. I can guess this is not a clean way of doing it, but it works for now.
I'm building and running both containers first. Then, when both api and db are up, i'm remotely executing migration commands using docker exec. wait-for-it script is not needed here.
run.sh
#!/bin/bash
docker-compose up -d --build atlanta-ms main-db
docker exec atlanta bash -c "dotnet ef migrations add InitialMigration && dotnet ef database update"
rest api Dockerfile
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
docker-compose.yml
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
The drawback of this solution is that rest api is running in detached mode, so i cannot stop it just by doing ctrl + c in console. Adding docker attach atlanta line at the end of run.sh script works (i can stop container by simple ctrl + c), but it doesn't work with several containers (cannot attach to more than one container) so i have to write simple stop script and call it independently from run.sh to stop containers, what is a little inconvenient.
I would be very grateful if someone could tell me how can i attach to few containers, so i could stop them all with ctrl + c (thats how the docker-compose up service1 service2 service3 without "-d" flag works)

Resources