Reputation: 1935
First, I am new to docker containers, I don't know much about how they are running, but I have this setup:
The API is reachable at https://localhost:44384/api/weatherforecast The containerized angular app is reachable at https://localhost:4200
If I am running the angular app without docker, after fixing the CORS issues with a proxy, I am able to connect to https://localhost:44384/api/weatherforecast. However, when I am running the dockerized version I am receiving the following error:
Failed to load resource: the server responded with a status of 504 (Gateway Timeout)
In the VS Console I see this error:
clearance_1 | [HPM] Error occurred while trying to proxy request /api/weatherforecast from loccoalhost:4200 to https://localhost:44384 (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)
It seems to be a connectivity issue, so I dig a bit on the internet and I tried to bring these two containers under the same network.
Here are the steps: 1. Create a bridge "test" network
docker network create test
docker network connect test [container id 1]
docker network connect test [container id 2]
Other potential useful stuff:
docker-compose.yml :
version: "3.7"
services:
clearance:
build:
# network: host
context: .
dockerfile: DockerFileLocal
ports:
- 4200:4200
volumes:
- /app/node_modules
- .:/app
proxy.conf.json
{
"/api/*": {
"target": "https://localhost:44384",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
}
}
What am I missing?
Upvotes: 5
Views: 11436
Reputation: 7978
Add a section to your compose file under each service that declares static IP's for each container:
services:
webserver:
build:
dockerfile: Dockerfile
context: .
depends_on:
- some_other_container
ports:
- "443:443"
environment:
- MY_VAR='my_val'
########### ADD THIS PART ##############
networks:
dev_net:
ipv4_address: "192.168.0.50"
and add a section at the same level as services
for the network:
networks:
dev_net:
name: my_dev_net
driver: overlay
ipam:
config:
- subnet: "192.168.0.0/24"
Then make sure that the hosted applications are configured to use those IP's to communicate. If IP's are not manually assigned, docker will pretty much act like a DHCP server and give whatever IP's it decides to assign.
To clarify: I think part of the problem you are having is due to Docker networking itself: on Mac and Windows, Docker can't really provide a fully routable virtual network where the IP's assigned to containers are accessible directly from the outside. No matter what solution you go with, it's going to have to work around that limitation. The only way to make a container accessible from the outside is to directly bind it to ports on the host (using docker run -p [source_port]:[host_port]
)
Here is a demo that should clarify my suggestion. This will:
docker-compose.yml
filelocalhost
instead of the private IP (since that is not accessible from outside docker)The purpose of this is to present a minimal example that: allows two Docker containers to communicate; over the docker private network; using private static IP addresses; while also binding to a port on the host system; allowing connections inbound to the container from outside the docker private network.
version: "3.7"
services:
c1:
build:
dockerfile: Dockerfile
context: ./c1
ports:
- "8080:8080"
networks:
dev_net:
ipv4_address: "192.168.0.50"
c2:
build:
dockerfile: Dockerfile
context: ./c2
depends_on:
- c1
networks:
dev_net:
ipv4_address: "192.168.0.51"
networks:
dev_net:
name: test_dev_net
driver: overlay
external: false
ipam:
config:
- subnet: "192.168.0.0/24"
FROM alpine:3.7
RUN apk update && apk upgrade && apk add openssl
COPY run.sh /run.sh
CMD ["/run.sh"]
#!/bin/sh
echo "HELLO, WORLD!" >> test_file.txt
openssl req -x509 -newkey rsa:2048 -keyout key.pem \
-out cert.pem -days 365 -nodes -subj /C=\/ST=\/L=\/O=\/OU=\/CN=\/
openssl s_server -key key.pem -cert cert.pem -accept 8080 -HTTP &
sleep 25
FROM alpine:3.7
RUN apk update && apk upgrade && apk add curl;
COPY run.sh /run.sh
CMD ["/run.sh"]
#!/bin/sh
c1_url="https://192.168.0.50:8080/test_file.txt"
for _ in $(seq 0 2); do
curl -k -g ${c1_url}
sleep 5
done
$ docker-compose up & \
sleep 10 && \
curl -k -g "https://localhost:8080/test_file.txt"
[3] 63380
Starting docker_c1_1 ... done
Starting docker_c2_1 ... done
Attaching to docker_c1_1, docker_c2_1
c1_1 | Generating a RSA private key
c1_1 | .....................................+++++
c1_1 | writing new private key to 'keys/key.pem'
c1_1 | No value provided for Subject Attribute C, skipped
c1_1 | No value provided for Subject Attribute ST, skipped
c1_1 | No value provided for Subject Attribute L, skipped
c1_1 | No value provided for Subject Attribute O, skipped
c1_1 | No value provided for Subject Attribute OU, skipped
c1_1 | No value provided for Subject Attribute CN, skipped
c2_1 | % Total % Received % Xferd Average Speed Time Time Time Current
c2_1 | Dload Upload Total Spent Left Speed
100 42 0 42 0 0 3230 0 --:--:-- --:--:-- --:--:-- 3230
c2_1 | HELLO, WORLD! <<<<------ Container #2 curl output
c2_1 | HELLO, WORLD!
c2_1 | HELLO, WORLD!
HELLO, WORLD! <<<<------ Host curl output
docker_c2_1 exited with code 0
c1_1 | DONE. Exiting...
docker_c1_1 exited with code 0
[3] Done docker-compose up
$
So this solution will work to allow docker-compose to build containers which use static IP addressing on the private docker network and which are also exposed via port binding on the host.
Upvotes: 1
Reputation: 1778
I had a similar issue with an angular app and an API both running in separate Docker containers.
Both apps were individually working fine with the following setup :
Angular
running at http://localhost:4200
API
running at http://localhost:8080
The Angular app couldn't reach the API.
The following code gave me network related errors all the time.
this.http.get('http://localhost:8080').subscribe(console.log);
Links
Link to containers in another service. Either specify both the service name and a link alias (SERVICE:ALIAS), or just the service name. Containers for the linked service are reachable at a hostname identical to the alias, or the service name if no alias was specified.
When a container needs to reach another container via the network, we need to create a link.
I ended up creating a link to the api
service in the angular
service definition in the docker-compose.yml
version: "2"
services:
api:
build:
context: .
dockerfile: ./api/Dockerfile
volumes:
- ./api:/usr/src/app
ports:
- "8080:8080"
angular:
build:
context: .
dockerfile: ./angular/Dockerfile
volumes:
- ./angular:/usr/src/app
ports:
- "4200:4200"
links:
- api
Then I fixed the network error by replacing localhost
with api
in the Angular app.
this.http.get('http://api:8080').subscribe(console.log);
You don't need a proxy. However, you might have to tweak your config to make it work.
Upvotes: 2