1

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 :

1 Answer 1

1

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!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.