MakotoE
MakotoE

Reputation: 2109

How do you set up MySQL in Docker and connect to it?

I'm trying to set up an e2e test. For this, I need a local test database, preferably in Docker so that test setup is simple. Here is a minimal project showing what I currently have: https://gitlab.com/MakotoE/mysql-test If this issue is fixed, npm test will finish with exit code 0. This is being run on Windows 10.

In main.js, I start an instance of the Docker image mysql:8.0 like this:

const command = 'docker run -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 3306:3306 -d mysql:8.0';
ChildProcess.execSync(command);

I want to connect to it with mysql2, but it fails with an Error: connect ETIMEDOUT.

await mysql.createConnection({
    host: 'localhost',
    user: 'root',
});

If I try to connect to the database created in the JavaScript code, through command prompt (mysql -uroot), I get this error: ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0. If I create the container in command prompt with the same docker run command used in the code, I can connect successfully, so this issue might be related to ChildProcess.execSync, but I don't know how I can fix this.

How can I fix my code so that I can start a MySQL server in Docker and connect to it in Node.js running on Windows 10?

Edit: I'm not sure if this is related, but running this on Debian shows this error message when creating the container:

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock:
Post http://%2Fvar%2Frun%2Fdocker.sock/v1.39/containers/57f5b631e551466e1f9928ba62f7a5e2a5ad2a481da4686bda8684f1a71b8d7/stop: dial unix /var/run/docker.sock: connect: permission denied

And connection fails with ETIMEDOUT.

Edit: I added branch secondAttempt where I unsuccessfully tried running all commands outside the .js file, through NPM scripts. After running the test for this branch, you must manually stop the Docker container.

In the mysql -uroot command, it fails with:

ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

which I believe is the same error as experienced previously, with different messages (due to different clients).

This experiment tells me two things: ChildProcess.execSync is not the root cause to this issue, and that there is something about this system (whether it is Docker, or the TCP connection to the Docker) that prevents scripted commands.

Upvotes: 0

Views: 965

Answers (1)

MakotoE
MakotoE

Reputation: 2109

I finally figured this out. All I need to do is wait 15 seconds before connecting.

The mistake I made is a common one: not reading the readme. In the mysql Docker Hub page, under section "No connections until MySQL init completes", it mentions how you must wait for database initialization to complete. The example repos achieve this via looping to retry the connection, but I think its simpler to delay for a set period of time.

Before, I was under the impression that I only needed to wait ~1 second after docker run, but actually it takes ~14 seconds for the database to be initialized. The fix was as simple as using setTimeout to wait 15-20 seconds before connecting to the database. I have given an example in branch fixed!.

Upvotes: 1

Related Questions