Actualmente, tengo un problema extraño en el sentido de que cuando intento conectarme al contenedor de la base de datos de Oracle desde un contenedor de Apache, obtendré "TNS: se agotó el tiempo de espera de conexión" del método oci_error. Mi código PHP es el siguiente:
<?php $objConnect = oci_connect('SYSTEM', 'xxxxxxxxxx', 'xxxx/xxxxx'); if($objConnect) { echo "from Docker Oracle Server Connected" . PHP_EOL; } else { echo "Cannot connect to Oracle Server" . PHP_EOL; var_dump( oci_error() ); } ?>Mi código docker para ejecutar Oracle Database es:
docker run --name orcl_12c_r_1 -p 1521:1521 -p 5500:5500 -e ORACLE_SID=xxxxx oracle/database:12.1.0.2-se2Y abrí mi Apache con este docker-compose.yml:
version: '3' services: oraclelinuxphp: build: context: ./oraclelinuxphp dockerfile: Dockerfile # install httpd and PHP here. ports: - "8080:80" volumes: - ./web:/var/www/htmlSin embargo, este problema se resolvió cuando agregué network_mode host a 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"Todavía soy un novato en lo que respecta a Docker y, a partir de aquí, creo que me falta algo en Docker. Podría conectarme a Oracle Database en el contenedor del servidor desde la aplicación Oracle SQL Developer en mi escritorio sin ningún problema. Además, también probé la ruta que no es de Docker, y el PHP que no es de Docker también podría conectarse a esta base de datos de Oracle.
Así que creo que este es un problema de Docker. ¿Que me estoy perdiendo aqui? ¿Cómo puedo hacer que Apache Container pueda conectarse a Oracle Database Container en este caso?
Nota: estoy usando:
Ocurre algo de magia conveniente cuando se utiliza docker-compose vs. docker run. La red se establecerá implícitamente.
Un ejemplo:
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 -dEstos contenedores podrán comunicarse entre sí debido al hecho de que se ha establecido una red predeterminada. ( nombre_carpeta_predeterminado )
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 msAhora, su escenario es que su contenedor de base de datos no está conectado a la red creada por docker-compose. Me gusta esto:
docker run --rm -it --name c3 alpine sh -c 'ping -c1 c1' ping: bad address 'c1'Puede definir la red para su comando de ejecución (esto funcionará):
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 msPara agrupar todos mis diferentes componentes, siempre los defino en docker-compose donde nombro explícitamente la red así:
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 es solo para cosas imperativas ad-hoc. Incluiría el servicio de la base de datos en el archivo docker-compose.yml o en un archivo separado como docker-compose -f mydb.yml up -d donde se define el nombre de la red. A partir de ahí, sus contenedores podrán comunicarse con la base de datos.
¡Buena suerte!