Belgium grabbed the lead in the 13th minute when Fernandinho diverted into his own net from a corner. It came moments after Brazil had gone close from a corner themselves with Thiago Silva bundling a miscued effort against the woodwork.
Belgium doubled their lead from a quick counter-attack just after the half-hour mark. Romelu Lukaku carried the ball forward from deep inside his own half and fed Kevin De Bruyne outside the area. The Manchester City midfielder lashed home a fierce long-range shot.
Brazil went close to pulling one back when Philippe Coutinho forced Thibaut Courtois into a good save with a fine effort from distance.
De Bruyne threatened again from a free-kick but Allison tipped over the bar. A compelling first half ended with Belgium leading 2-0.
Brazil had two penalty appeals rejected as they pushed to get back into the game early in the second half.
Serbian referee Milorad Mazic seemed unimpressed with Neymar as he went down in the area after a challenge from Fellaini and waved play on. Gabriel Jesus appeared to have a stronger claim after being clipped by Vincent Kompany but, despite a VAR review, nothing was given.
Brazil did pull one back 14 minutes from time when Coutinho floated in a fine cross and substitute Renato Augusto guided in a header. But it was not enough as Neymar, Coutinho and Augusto all saw late chances go begging.
Belgium will play France in Saint Petersburg on Tuesday evening.