Tengo 2 aplicaciones que son bases de código separadas, y cada una tiene su propia base de datos en la misma instancia del servidor db.

Estoy tratando de replicar esto en Docker, localmente en mi computadora portátil. Quiero poder hacer que ambas aplicaciones usen la misma instancia de base de datos.

Me gustaría

  • Ambas aplicaciones comenzarán en Docker al mismo tiempo

  • ambas aplicaciones para poder acceder a la base de datos en localhost

  • los datos de la base de datos son persistentes

  • poder ver los datos en la base de datos usando un IDE en localhost

Entonces, cada una de mis aplicaciones tiene su propio archivo dockerfile y docker-compose.

En app1, inicio la instancia de docker de la aplicación que está vinculada a la base de datos. Todo comienza bien.

Cuando intento iniciar app2, aparece el siguiente error:

ERROR: for app2_mssql_1  Cannot start service mssql: driver failed programming external connectivity on endpoint app2_mssql_1 (12d550c8f032ccdbe67e02445a0b87bff2b2306d03da1d14ad5369472a200620): Bind for 0.0.0.0:1433 failed: port is already allocated

¿Cómo puedo hacer que ambos se ejecuten al mismo tiempo? ¡AMBAS aplicaciones deben poder acceder a las tablas de la base de datos de los demás!

Aquí están los archivos docker-compose.yml

App1:

version: "3"
services:
  web:
    build:
      context: .
      args:
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - mssql
  mssql:
      image: 'microsoft/mssql-server-linux'
      ports:
          - '1433:1433'
      environment:
          - ACCEPT_EULA=Y
          - SA_PASSWORD=P455w0rd!
      volumes:
          - app1_db:/var/lib/mssql/data
volumes:
  app1_db:

Y aquí está app2:

version: "3"
services:
  web:
    build:
      context: .
      args:
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - mssql
  mssql:
      image: 'microsoft/mssql-server-linux'
      ports:
          - '1433:1433'
      environment:
          - ACCEPT_EULA=Y
          - SA_PASSWORD=P455w0rd!
      volumes:
          - app2_db:/var/lib/mssql/data
volumes:
  app2_db:

¿Debo usar el mismo volumen en cada archivo docker-compose? Supongo que el problema está en cada aplicación. Estoy activando 2 instancias de db diferentes, cuando en realidad supongo que solo quiero una, ¿y todas mis aplicaciones la usarán?

0
user3437721 20 oct. 2017 a las 16:46

3 respuestas

La mejor respuesta

Cómo funciona docker-compose up :

Suponga que su aplicación está en un directorio llamado myapp y su docker-compose.yml

Cuando ejecuta docker-compose, sucede lo siguiente:

  1. Se crea una red llamada myapp_default.
  2. Se crea un contenedor utilizando la configuración de la web. Se une a la red myapp_default bajo el nombre web.
  3. Se crea un contenedor utilizando la configuración de db. Se une a la red myapp_default bajo el nombre db.

Si ejecuta el segundo docker-compose.yml en una carpeta diferente myapp2, entonces el nework será myapp2_default.

La configuración actual crea dos volúmenes, dos contenedores de bases de datos y dos aplicaciones. Si puede hacer que se ejecuten en la misma red y ejecutar la base de datos como el contenedor único, funcionará.

No creo que espere dos contenedores de bases de datos dos dos volúmenes.

Enfoque 1:

docker-compose.yml como una sola composición.

version: "3"
services:
  app1:
    build:
      context: .
      args:
    volumes:
      - .:/app # give the path depending up on the docker file of app1.
    ports:
      - "3030:3000"
    depends_on:
      - mssql
  app2:
    build:
      context: .
      args:
    volumes:
      - .:/app # give the path depending up on the docker file of app2.
    ports:
      - "3032:3000"
    depends_on:
      - mssql
  mssql:
      image: 'microsoft/mssql-server-linux'
      ports:
          - '1433:1433'
      environment:
          - ACCEPT_EULA=Y
          - SA_PASSWORD=SqlServer1234!
      volumes:
          - app_docker_db:/var/lib/mssql/data
volumes:
  app_docker_db:

Enfoque 2:

Para aislarlo aún más, aún desea ejecutarlos como archivos de composición separados, crear tres archivos de composición con red.

Docker-compose.yml para base de datos con red

version: "3"
    services:
      mssql:
          image: 'microsoft/mssql-server-linux'
          ports:
              - '1433:1433'
          environment:
              - ACCEPT_EULA=Y
              - SA_PASSWORD=SqlServer1234!
          volumes:
              - app_docker_db:/var/lib/mssql/data
          networks:
                - test_network
volumes:
    app_docker_db
    
networks:
    test_network:
  1. docker-compose.yml para app1

Elimine el contenedor de la base de datos y agregue las líneas siguientes a su archivo de redacción

version: "3"
services:
  app1:
    build:
      context: .
      args:
    volumes:
      - .:/app # give the path depending up on the docker file of app1.
    ports:
      - "3030:3000"    
networks:
    default:
        external:
          name: my-pre-existing-network

Haga lo mismo para otra docker-compose reemplazando el archivo docker-compose.

Hay muchas otras opciones para crear archivos docker-compose. Configure la red predeterminada y use una red preexistente

1
Community 20 jun. 2020 a las 09:12

La parte ports en el archivo docker-compose vinculará el puerto del contenedor al puerto del host, lo que causa conflicto de puertos en su caso.

Debe eliminar la parte ports de al menos uno del archivo de redacción. De esta manera, docker-compose puede estar preparado para ambos. Y puede tener acceso a ambas aplicaciones al mismo tiempo. Pero recuerde que ambas aplicaciones se colocarán en puentes de red separados.

1
robert 20 oct. 2017 a las 13:57

Estás exponiendo el mismo puerto (1433) dos veces a la máquina host. (Esto es lo que hace "puertos: ..."). Esto no es posible ya que bloquearía el mismo puerto en su host (eso es lo que dice el mensaje).

Creo que la forma más común en estos casos es que vincule sus bases de datos a sus aplicaciones. (Consulte https://docs.docker.com/compose/compose-file/# enlaces). Al hacer esto, sus aplicaciones aún pueden acceder a las bases de datos en sus puertos comunes (1433), pero las bases de datos ya no son accesibles desde el host (solo desde el contenedor que está vinculado a él).

Otro error que veo en el archivo de redacción de Docker es que ambas aplicaciones están expuestas por los mismos puertos. Esto tampoco es posible por la misma razón. Sugeriría que cambie uno de ellos a "3000: 3001", para que pueda acceder a esta aplicación en el puerto 3001.

1
tvvk 20 oct. 2017 a las 13:58