Reputation: 5733
Currently, I have a strange issue in that when I try to connect to the Oracle Database container from an Apache Container, I will get "TNS: Connect Timeout Occurred" from oci_error method. My PHP code is as follow:
<?php
$objConnect = oci_connect('SYSTEM', 'xxxxxxxxxx', 'x.x.x.x/xxxxx');
if($objConnect)
{
echo "from Docker Oracle Server Connected" . PHP_EOL;
}
else
{
echo "Cannot connect to Oracle Server" . PHP_EOL;
var_dump( oci_error() );
}
?>
My docker code to run Oracle Database is:
docker run --name orcl_12c_r_1 -p 1521:1521 -p 5500:5500 -e ORACLE_SID=xxxxx oracle/database:12.1.0.2-se2
And I brought my Apache up with this docker-compose.yml:
version: '3'
services:
oraclelinuxphp:
build:
context: ./oraclelinuxphp
dockerfile: Dockerfile # install httpd and PHP here.
ports:
- "8080:80"
volumes:
- ./web:/var/www/html
However, this issue is resolved when I added network_mode host to the docker-compose.yml :
version: '3'
services:
oraclelinuxphp:
build:
context: ./oraclelinuxphp
dockerfile: Dockerfile # install httpd and PHP here.
ports:
- "8080:80"
volumes:
- ./web:/var/www/html
network_mode: "host"
I am still a rookie when it comes to Docker, and from here, I believe I am missing something in Docker. I could connect to the Oracle Database in the container on the server from Oracle SQL Developer app on my desktop without any problem. In addition, I also tried the non-Docker route, and the non-Docker PHP could also connect to this Oracle Database as well.
So I believe this is Docker issue. What am I missing here? How can I make it so the Apache Container could connect to the Oracle Database Container in this case?
Note: I am using :
Upvotes: 1
Views: 3649
Reputation: 4471
There is some convenient magic happening when utilizing docker-compose vs. docker run. Network will implicitly be established.
An example:
cat > docker-compose.yml <<EOF
version: '3'
services:
c1:
image: alpine
container_name: c1
command: "sleep 1000"
c2:
image: alpine
container_name: c2
command: "sleep 1000"
EOF
# fire up the containers and detach
docker-compose up -d
These containers will be able to talk to each other due to the fact a default network has been established. (folder_name_default)
docker network ls -fname=demo1
NETWORK ID NAME DRIVER SCOPE
e3777f15f5aa demo1_default bridge local
# c1 can talk to c2
docker-compose exec c1 sh -c 'ping -c1 c2'
PING c2 (172.30.0.2): 56 data bytes
64 bytes from 172.30.0.2: seq=0 ttl=64 time=3.741 ms
# c2 can talk to c1
docker-compose exec c2 sh -c 'ping -c1 c1'
PING c1 (172.30.0.3): 56 data bytes
64 bytes from 172.30.0.3: seq=0 ttl=64 time=0.798 ms
Now, your scenario is that your database container is not attached to the network created by docker-compose. Like this:
docker run --rm -it --name c3 alpine sh -c 'ping -c1 c1'
ping: bad address 'c1'
You can define network for your run-command (this will work):
docker run --rm --net demo1_default -it --name c3 alpine sh -c 'ping -c1 c1'
PING c1 (172.30.0.3): 56 data bytes
64 bytes from 172.30.0.3: seq=0 ttl=64 time=0.571 ms
# make sure c3 keeps running while we try to contact it.
docker run --rm --net demo1_default -d -it --name c3 alpine sh -c 'sleep 1000'
# yes it works!
docker-compose exec c1 sh -c 'ping -c1 c3'
PING c3 (172.30.0.4): 56 data bytes
64 bytes from 172.30.0.4: seq=0 ttl=64 time=0.314 ms
To bundle all my different components together, I always define them in docker-compose where I explicitly name the network like this:
cat > docker-compose.yml <<EOF
version: '3'
services:
c1:
image: alpine
container_name: c1
command: "sleep 1000"
networks:
- mynet
c2:
image: alpine
container_name: c2
command: "sleep 1000"
networks:
- mynet
networks:
mynet:
EOF
docker run
is just for ad-hoc imperative stuff. I would include the the database service in the docker-compose.yml file or a separate file like docker-compose -f mydb.yml up -d
where network-name is defined. From there on your containers will be able to communicate with the database.
Best of luck!
Upvotes: 1