Should I store relation counts as their own columns, or will indexes be fast enough?
Several comments:

We can't guess what's fast enough for you. As the comment above says, it depends on the speed of your hardware, but it also depends on how well your data fits in RAM, it depends on how frequently the query is run, it depends on how much data exists, it depends on how fast you need it to be.
Your app might need to denormalize or cache this value, but we don't know if your app operates at a scale where it needs this yet. Be conservative with such optimizations. They might be needed, but if they are not needed, it just adds complexity to your app for no reason.

You don't need a join to count rows in the likes table for a given post, as @nbk points out. Probably you do need to use a join if you want to count the likes for many posts, but we can't guess if you need to do that.

Given the attributes of the likes table you've shown, why do you even need this table? You don't record the person who added each like, so you can't implement a feature to let users reverse their like. You also don't record any other attributes, such as the datetime of the like, or the type of like (e.g. facebook's like, heart, care, wow, sad, angry). Why bother having the table?

If you wonder if it will still be fast enough once it reaches millions of rows, then test it with millions of rows. This is part of your job as a software developers: come up with a way to test things, don't guess or expect someone else to tell you the right answer. You can load a table with millions of random rows for likes, and then try out your query. This will be more accurate than a Stack Overflow answer, because it will be running on your server's hardware. We don't have to make assumptions about the speed or capacity of your environment.