Sergio Conceicao's side were on the defensive for long periods at the Estadio do Dragao, but a series of superb saves from Porto keeper Agustin Marchesin secured the point they needed to advance.
Pep Guardiola saluted Manchester City's "incredible personality" after they sealed first place in Champions League Group C with a 0-0 draw against Porto that also sent the hosts in the last 16.
City's Gabriel Jesus was denied a late winner after VAR ruled out his goal.
Guardiola's team had already booked their place in the last 16 after winning their first four games and, with top spot now secured, the boss can now rest players for their final match against Marseille next week.
"Congratulations to my team for this game and finishing first. We didn't concede a shot on target or a corner all game," Guardiola said on Tuesday after the match.
"We struggled to score but we played really well with incredible personality and many things about the game were brilliant.
"It's difficult with eight or nine of their players defending in the box.
"We came here to finish first. We played for the win and we deserved it, but deserve in football is a fake word because the result dictates everything."
Guardiola insists City will thrive in the Champions League this season as they bid to make amends for last term's shock quarter-final defeat against Lyon.
City have never won the Champions League and Guardiola, who last lifted the trophy with Barcelona in 2011, has been unable to take them past the quarter-finals.
Finishing on top of the group was the first step towards that target and Guardiola will be encouraged by City's improved defence.
They have conceded just six goals in their last 13 games in all competitions, a run that includes four successive Champions League clean sheets.
"It's more than the results. We played really well in all the games. Eleven shots on target against Olympiakos and against Marseille as well and today we had lots of chances," Guardiola said.
"The way we played, the courage, and defensively we were so good."
Guardiola made seven changes as Kevin De Bruyne, Riyad Mahrez and Kyle Walker were among those resting on the bench following the 5-0 thrashing of Burnley.
Raheem Sterling felt he should have had an early penalty when Malang Sarr thudded into him without getting the ball, but VAR decided not to intervene despite the strong claim.
With Sergio Aguero still troubled by a knee injury and Jesus on the bench, Ferran Torres started up front for City.
Torres was denied the opening goal by a fine save from Marchesin after the Spaniard raced onto Phil Foden's pass.
City had 70 percent of the first half possession and Sterling almost made the breakthrough when he cut in from the left for a fierce drive that was cleared off the line by Zaidu Sanusi.
Cautious Porto finally showed a little ambition early in the second half when Sergio Oliveira tested Ederson from long range.
Sterling carried City's biggest threat and should have put them ahead when Foden's sublime pass put him clean through, only for Marchesin to rush from his line to make the save.
Marchesin denied the visitors again with a superb save from Torres' overhead kick after City defender Ruben Dias accidentally cleared Sterling's effort off the Porto line.
Bernardo Silva's low drive forced another good stop from Marchesin, who made an even better one-handed save to keep out Eric Garcia's header.
Jesus thought he had broken Marchesin's brilliant resistance in the 80th minute with a tap-in from the rebound after the Porto keeper had tipped his header onto the bar.
But after lengthy City celebrations, the goal was ruled out by VAR for offside against Silva during the build-up.