Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

docker-compose & Exposed Ports

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We need to get a database running: MySQL, Postgresql, whatever. If you already have one running, awesome! All you need to do is copy your DATABASE_URL environment variable, open or create a .env.local file, paste, then change it to match whatever your local setup is using. If you decide to do this, feel free to skip ahead to the end of chapter 4 where we configure the server_version.

Docker Just for the Database

For me, I do not have a database running locally on my system... and I'm not going to install one. Instead, I want to use Docker. And, we're going to use Docker in an interesting way. I do have PHP installed locally:

php -v

So I won't use Docker to create a container specifically for PHP. Instead I'm going to use Docker simply to help boot up any services my app needs locally. And right now, I need a database service. Thanks to some magic between Docker and the Symfony binary, this is going to be super easy.

To start, remember when the Doctrine recipe asked us if we wanted Docker configuration? Because we said yes, the recipe gave us docker-compose.yml and docker-compose.override.yml files. When Docker boots, it will read both of these... and they're split into two pieces just in case you want to also use Docker to deploy to production. But we're not going to worry about that: we just want to use Docker to make life easier for local development.

version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
image: postgres:${POSTGRES_VERSION:-13}-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe}
POSTGRES_USER: ${POSTGRES_USER:-symfony}
volumes:
- db-data:/var/lib/postgresql/data:rw
... lines 14 - 22

version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
... lines 8 - 9

These files say that they will boot a single Postgres database container with a user called symfony and password ChangeMe:

Tip

The username changed from symfony to app in the newest recipe version.

It will also expose port 5432 of the container - that's Postgres's normal port - to our host machine on a random port. This means that we're going to be able to talk to the Postgresql Docker container as if it were running on our local machine... as long as we know the random port that Docker chose. We'll see how that works in a minute.

By the way, if you want to use MySQL instead of Postgres, you absolutely can. Feel free to update these files... or delete both of them and run:

php bin/console make:docker:database

to generate a new compose file for MySQL or MariaDB. I'm going to stick with Postgres because it's awesome.

At this point, we're going to start Docker and learn a bit about how to communicate with the database that lives inside. If you're pretty comfortable with Docker, feel free to skip to the next chapter.

Starting the Container

Anyways, let's get our container running. First, make sure you have Docker actually installed on your machine: I won't show that because it varies by operating system. Then, find your terminal and run:

docker-compose up -d

The -d means "run in the background as a daemon". The first time you run this, it'll probably download a bunch of stuff. But eventually, our container should start!

Communicating with the Container

Cool! But now what? How can we talk to the container? Run a command called:

docker-compose ps

This shows info about all the containers currently running... just one for us. The really important thing is that port 5432 in the container is connected to port 50700 on my host machine. This means that if we talk to this port, we will actually be talking to that Postgres database. Oh, and this port is random: it'll be different on your machine... and it'll even change each time we stop and start our container. More on that soon.

But now that we know about port 50700, we can use that to connect to the database. For example, because I'm using Postgres, I could run:

psql --user=symfony --port=50700 --host=127.0.0.1 --password app

That means: connect to Postgres at 127.0.0.1 port 50700 using user symfony and talking to the app database. All of this is configured in the docker-compose.yml file. Copy the ChangeMe password because that last flag tells Postgres to ask for that password. Paste and... we're in!

If you're using MySQL, we can do this same thing with a mysql command.

But, this only works if we have that psql command installed on our local machine. So let's try a different command. Run:

docker-compose ps

again. The container is called database, which comes from our docker-compose.yml file. So we can change the previous command to:

docker-compose exec database psql --username symfony --password app

This time, we're executing the psql command inside the container, so we don't need to install it locally. Type ChangeMe for the password and... we're back in!

The point is: just by running docker-compose up, we have a Postgres database container that we can talk to!

Stopping the Container

Btw, when you're ready to stop the container later, you can run:

docker-compose stop

That basically turns the container off. Or you can run the more common:

docker-compose down

which turns off the containers and removes them. To start back up, it's the same:

docker-compose up -d

But notice that when we run docker-compose ps again, the port on my host machine is a different random port! So, in theory, we could configure the DATABASE_URL variable to point to our Postgres database, including using the correct port. But that random port that keeps changing is going to be annoying!

Fortunately, there's a trick for this! It turns our, our app is already configured, without us doing anything! That's next.

Leave a comment!

13
Login or Register to join the conversation
odds Avatar

I unfortunately also have a problem connecting. In docker-compose.yml a have the following setup:

      POSTGRES_DB: ${POSTGRES_DB:-app}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-none}
      POSTGRES_USER: ${POSTGRES_USER:-symfony}

Now, when I run the command psql --user=symfony --port=49153 --host=127.0.0.1 --password app and give the password, I get the error:

psql: error: connection to server at "127.0.0.1", port 49153 failed: FATAL:  password authentication failed for user "symfony"

However, when I use the command docker-compose exec database psql --user app --password app and give the password, I do get in which makes no sense to me. Could you please demystify?

Reply
odds Avatar

by the way, symfony console doctrine:database:create gives the following error:

An exception occurred in the driver: SQLSTATE[08006] [7] connection to server at "127.0.0.1", port 49154 failed: FATAL:  password authentication failed for user "app"
Reply
Laurent-G Avatar
Laurent-G Avatar Laurent-G | posted 4 days ago

Hello, i have a problem when i run this command
psql --user=app --port=52439 --host=127.0.0.1 --password app, the result is :

psql: The term 'psql' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Docker is running on Windows 11, if i execute
docker-compose ps, the result is :

NAME                     COMMAND                  SERVICE             STATUS              PORTS
mixed_vinyl-database-1   "docker-entrypoint.s…"   database            running             0.0.0.0:52439->5432/tcp

What is doing to resolve this mistake ?

Thanks,
Laurent

Reply

Hey Laurent-G,

It seems like you're missing that psql command installed locally, though the error message is a bit weird to me. Do you have psql installed locally? You should have it installed to be able to connect to the DB from Docker. On my Mac when I execute psql --version it shows me psql (PostgreSQL) 14.5 (Homebrew), IIRC I installed the PostgreSQL via Brew package manager locally and it brought me that psql command. If you don't have PostgreSQL installed locally - try to install it first. But brew is specific for Mac, you should find a way to install PostgreSQL on Windows.

Of if you don't want to (or cannot) install it locally - see the next chapter where we execute that psql command directly from the Docker container.

Cheers!

Reply
Laurent-G Avatar
Laurent-G Avatar Laurent-G | victor | posted 3 days ago

Thanks Victor for your answer.

i don't have installed psql locally. I'm going to see for install psql on my windows system.
i already saw in the next chapter the command to execute psql from Docker container and it's work very good.

Thanks a lot,
Laurent

Reply

Hey Laurent-G,

Glad that executing it from the Docker container works for you, thanks for confirming! I bet you just need to install PostgreSQL and it will bring that psql command into your system automatically. Or you can just ignore it and execute it directly from the Docker container - that's the benefit of having Docker ;)

Cheers!

Reply
red_smeg Avatar
red_smeg Avatar red_smeg | posted 1 month ago

Is there a version of this with a mysql container. Tried using Postgres's but getting data from an existing mysql database to the Postgres container is too hard

Reply
red_smeg Avatar
red_smeg Avatar red_smeg | red_smeg | posted 1 month ago | edited

figured it out (lost a lot of time because of the stupid ! at the start of the !ChangeMe! password......)

  1. change the DATABASE_URL in the .env file to the mysql one.
  2. remove the !ChangeMe! password docker-compose doesn't like it when it tries to create a mysql container
  3. comment out the the postgres lines in the docker-compose.yml (From the services: tag to the end)
  4. Add the following lines to your docker-compose.yml
services:
  database:
    container_name: database
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: yoursecretrootpassword
      MYSQL_DATABASE: yourdbname
      MYSQL_USER: app
      MYSQL_PASSWORD: yourpasswd   <-- the one you used in the .env file
    ports:
      - '3306:3306'
    volumes:
      - ./mysql:/var/lib/mysql`
2 Reply

Hey Red,

I'm happy to see you were able to find the solution! And thanks for sharing it with others :)

Cheers!

Reply
Markchicobaby Avatar
Markchicobaby Avatar Markchicobaby | posted 1 month ago

Hi, running command "docker-compose exec database psql --username symfony --password app" I'm prompted for a password, which I enter (to match the one in the docker compose file which is !ChangeMe! but then... it just hangs. Cursor flashes, but no response at all. I can connect to the database successfully using DBeaver (a GUI database client), it connects and can see the database fine. This is what I see at the terminal:
`$ docker-compose exec database psql --username app --password app
Password: !ChangeMe!

`

Reply

Hey Mark,

Hm, could you change that "!ChangeMe!" password in .env files to something without special chars, I guess that the exclamation char (!) may cause issues. And then restart the server and try to connect with the new credentials.

Cheers!

Reply
Thomas A. Avatar
Thomas A. Avatar Thomas A. | posted 3 months ago

Hi and thanks for this new tutorial!

I've an error when I run docker-compose exec database psql --username symfony --password app:
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "symfony" does not exist

Am I missing something?

OS: Linux Mint 20.3 Cinnamon 5.2.7
Kernel: 5.4.0-124-generic
Docker version 20.10.17, build 100c70
docker-compose version 1.28.6, build 5db8d86f

Reply

Hey Thomas A.!

Oh sheesh - try this instead - changing "symfony" to "app":


docker-compose exec database psql --username app --password app

Explanation: RIGHT after recording, the recipe was updated - you probably have the new version https://github.com/symfony/...

Let me know if that helps - we'll need to add a note about it :).

Cheers!

2 Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "babdev/pagerfanta-bundle": "^3.7", // v3.7.0
        "doctrine/doctrine-bundle": "^2.7", // 2.7.0
        "doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
        "doctrine/orm": "^2.12", // 2.12.3
        "knplabs/knp-time-bundle": "^1.18", // v1.19.0
        "pagerfanta/doctrine-orm-adapter": "^3.6", // v3.6.1
        "pagerfanta/twig": "^3.6", // v3.6.1
        "sensio/framework-extra-bundle": "^6.2", // v6.2.6
        "stof/doctrine-extensions-bundle": "^1.7", // v1.7.0
        "symfony/asset": "6.1.*", // v6.1.0
        "symfony/console": "6.1.*", // v6.1.2
        "symfony/dotenv": "6.1.*", // v6.1.0
        "symfony/flex": "^2", // v2.2.2
        "symfony/framework-bundle": "6.1.*", // v6.1.2
        "symfony/http-client": "6.1.*", // v6.1.2
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/proxy-manager-bridge": "6.1.*", // v6.1.0
        "symfony/runtime": "6.1.*", // v6.1.1
        "symfony/twig-bundle": "6.1.*", // v6.1.1
        "symfony/ux-turbo": "^2.0", // v2.3.0
        "symfony/webpack-encore-bundle": "^1.13", // v1.15.1
        "symfony/yaml": "6.1.*", // v6.1.2
        "twig/extra-bundle": "^2.12|^3.0", // v3.4.0
        "twig/twig": "^2.12|^3.0" // v3.4.1
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
        "symfony/debug-bundle": "6.1.*", // v6.1.0
        "symfony/maker-bundle": "^1.41", // v1.44.0
        "symfony/stopwatch": "6.1.*", // v6.1.0
        "symfony/web-profiler-bundle": "6.1.*", // v6.1.2
        "zenstruck/foundry": "^1.21" // v1.21.0
    }
}