How do I connect to host MySQL from AWS SAM local docker instance?
Asked Answered
K

4

24

I am trying to invoke my Lambda function using sam local invoke but find that it cannot connect to my host MySQL. I tried adding --docker-network host but it also cannot connect

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 229, in _raise_for_status
    response.raise_for_status()
  File "/usr/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: http+docker://localhost/v1.35/networks/6ad3bd87e8437e8410145d169a4edf68d1b0247a67257ce7dd1208dac3664c82/connect

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/sam", line 11, in <module>
    load_entry_point('aws-sam-cli==0.5.0', 'console_scripts', 'sam')()
  File "/usr/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args[1:], **kwargs)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 47, in cli
    docker_network, log_file, skip_pull_image, profile)  # pragma: no cover
  File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 79, in do_cli
    stderr=context.stderr)
  File "/usr/lib/python3.6/site-packages/samcli/commands/local/lib/local_lambda.py", line 80, in invoke
    stdout=stdout, stderr=stderr)
  File "/usr/lib/python3.6/site-packages/samcli/local/lambdafn/runtime.py", line 83, in invoke
    self._container_manager.run(container)
  File "/usr/lib/python3.6/site-packages/samcli/local/docker/manager.py", line 61, in run
    container.create()
  File "/usr/lib/python3.6/site-packages/samcli/local/docker/container.py", line 115, in create
    network.connect(self.id)
  File "/usr/lib/python3.6/site-packages/docker/models/networks.py", line 57, in connect
    container, self.id, *args, **kwargs
  File "/usr/lib/python3.6/site-packages/docker/utils/decorators.py", line 19, in wrapped
    return f(self, resource_id, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/docker/api/network.py", line 248, in connect_container_to_network
    self._raise_for_status(res)
  File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 231, in _raise_for_status
    raise create_api_error_from_http_exception(e)
  File "/usr/lib/python3.6/site-packages/docker/errors.py", line 31, in create_api_error_from_http_exception
    raise cls(e, response=response, explanation=explanation)
docker.errors.APIError: 400 Client Error: Bad Request ("container cannot be disconnected from host network or connected to host network")

I noticed the last line:

docker.errors.APIError: 400 Client Error: Bad Request ("container cannot be disconnected from host network or connected to host network")

How do I fix this?

Kentledge answered 21/7, 2018 at 13:40 Comment(2)
Comparing what you have so far with this github repo might be helpfulDefensible
Can you clarify where your database is running? Is it in the cloud or on your local laptop or elsewhere? Can you connect to it from outside the container?Theatrician
P
11

I can't say why --docker-network host produces this error, but I don't think you need it. I can connect to MySQL running on my local machine from within SAM local, without any network overrides.

I do this by simply using my local IP (as opposed to localhost or 127.0.0.1) to connect to the database.

The following lambda function connects to my local MySQL just fine, provided I use my local IP, as revealed a tool like ipconfig.

'use strict';
var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : '192.168.1.6',
  user     : 'mike',
  password : 'password',
  database : 'logtest'
});

module.exports.hello = (event, context, callback) => {

  connection.connect();

  connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (error) throw error;
    console.log('The solution is: ', results[0].solution);
    const response = {
      statusCode: 200,
      body: JSON.stringify({solution: results[0].solution})
    };

    connection.end();

    callback(null, response);    
  });
};

Partial ipconfig output:

Ethernet adapter Local Area Connection 6:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::95c2:495c:7226:8ac2%39
   IPv4 Address. . . . . . . . . . . : 10.251.19.6
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

Wireless LAN adapter Wireless Network Connection:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::496a:d34d:8380:3b1c%15
   IPv4 Address. . . . . . . . . . . : 192.168.1.6
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

In this case, my lambda function can connect to local MySQL using 10.251.19.6 or 192.168.1.6.

Minimal example here.

Persephone answered 29/7, 2018 at 0:45 Comment(2)
I agree with the sentiment here. Though I'm not entirely sure why your host networking isn't working, that is unlikely to be functionally relevant for network clients.Theatrician
I'd been sitting with this problem for hours. Thanks for this answer!!Burgle
M
7

Could you post how you are starting mysql container locally? Hard to say whats going wrong with out more info.

Here is some general advice though.


If your running on a mac

You can just use special host name locally when configuring mysql client in container making the call. It will resolve locally with no --docker-network flag needed.

Ex:

host = 'docker.for.mac.localhost'

Or on newer installs of docker https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-17120-ce-mac49-2018-01-19

host = 'docker.for.mac.host.internal'

Ex python code.

import mysql.connector

host = 'docker.for.mac.host.internal'
cnx = mysql.connector.connect(user='scott', password='password',
                              host=host,
                              database='employees')
cnx.close()

If you are not on mac

Then make sure you are passing --docker-network when you start your mysql container it should look something like this.

docker run -d -v "$PWD":/var/lib/mysql -p 3306:3306 \
    --network lambda-local \
    --name mysql \
    mysql

Then when invoking locally

sam local invoke --docker-network lambda-local

Then in your lambda code you just use network --name you passed mysql container as hostname.

Ex:

import mysql.connector

host = 'mysql'
cnx = mysql.connector.connect(user='scott', password='password',
                              host=host,
                              database='employees')
cnx.close()
Mozzetta answered 4/9, 2018 at 13:22 Comment(0)
S
4

No configuration need just add below host while connection to your mysql

for windows : docker.for.win.localhost

for mac : docker.for.mac.localhost

const con = require('serverless-mysql')({
  config: {
   host     :  'docker.for.win.localhost',
   database : 'db-name',
   user     : 'root',
   connectTimeout : 5000,
   password : ''
 }
}); 
Sharronsharyl answered 16/7, 2020 at 6:17 Comment(1)
Note that docker.for.win.localhost is deprecated and the new official DNS name is host.docker.internalMa
V
0

You can check cases as follows:

  • Whether the docker port has a mapping.
  • Check the port of AWS's security group.
Vania answered 28/7, 2018 at 11:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.