City had a number of good chances after the break and also saw a late goal ruled out by VAR as the hosts scrapped their way to the 0-0 draw they probably set out for.
The first-half ended goalless with Porto defending deep and dealing with most of City's threat well.
There was a possible shout for a penalty when Raheem Sterling was caught inside the box on nine minutes, but his lack of an appeal probably made the VAR's decision easier.
Sterling had the best effort of the opening period, collecting the ball on the left of the Porto box, skipping past the full-back before sending a low angled shot in that was cleared off the line by Zaidu Sanusi.
Half-time: Porto 0-0 City
The game was becoming scrappy, with continued infringements and Porto players never wasting an opportunity to make the most of any challenges.
It felt like the Portuguese were intent on ensuring City never got into any rhythm, but the home side should have been punished when Phil Foden's clever pass saw Sterling edge past the last man but shoot straight at the keeper.
There was an extraordinary miss on 70 minutes when Fernandinho's cross found Ruben Dias a yard out but the former Benfica man effectively hooked the ball off the line and Ferran Torres' overhead kick was well saved by the body of the keeper.
City finally seemed to have broken the deadlock on 80 minutes - having just seen another gilt-edged opportunity spurned when Eric Garcia failed to connect cleanly when just a yard or so out and only the keeper to beat - but it was ruled out by VAR.
But a large slice of time had passed before it became clear the effort had been ruled out for an earlier offside against Jesus.
Porto keeper Marchesin was outstanding throughout and undoubtedly the only reason City didn't win this game.
All in all, not a classic but the result takes City through as group winners and Porto through as runners-up.
STAR MAN: FERNANDINHO
It was a scrappy, tough and physical battle at times - just the way the skipper likes it!
Ferna was at the centre of everything, playing more advanced and spraying balls around with confidence.
Great to have him back.
0 - Pep Guardiola has seen his side draw 0-0 in the Champions League for the first time in 59 games since a nil-nil against Shakhtar Donetsk in February 2015 when manager of Bayern Munich. Stalemate. pic.twitter.com/fnTDHigegi— OptaJoe (@OptaJoe) December 1, 2020
WHAT IT MEANS
City win Group C with a game to spare and will be handed a home second leg in the Round of 16.
City host Fulham in the Premier League - the second successive Saturday 3pm kick-off - at the Etihad Stadium.
Porto: Marchesín, Manafá (Nanu 73), Mbemba, Sarr, Monteiro Pinto Leite, Sanusi, Corona (Diaz 62), Uribe, Oliveira, Otávio, Marega (Evanilson 73)
Subs: Taremi, Nakajima, Marais Ramos, Silva Baró, Neto Lopes, Felipe Anderson, Martínez, Vieira, Meireles Costa
“We played incredibly well. We didn't concede one attack.
They are one of the best teams in Portugal, with the quality they have. We played exceptionally well.
“We came here to finish first. Big congratulations to the team for the group stage.
We played with huge personality, with courage. It is not easy with eight players in the box. “They are so strong with the full-backs, they are so fast.
“Even with that, we created enough chances to win. This is the most important thing.
“In general, I am more than delighted with the performance in these games.
“We have one left, nothing to play for, just to maintain the rhythm.
Now it’s time to forget Champions League and focus on Premier League.”
Fernandinho was happy with the 0-0 draw against Porto after City were confirmed as Group C winners.
The City skipper was at the heart of the battle that threatened to boil over at times, but says it was a good test and experience for his team.
“I think we tried to win the game and play our way but for them, it was important to get the point as and go through,” said Fernandinho, who got a vital 90 minutes under his belt.
“They fought the whole game to get the point and qualify.
“I think it's important for us as well because we controlled the game and created some chances to score.
“Unfortunately, we didn't score any goals, but it is still an important step for us to secure first position in the group.”
Ferna also praised the impact of compatriot Gabriel Jesus who was unlucky to see a late goal ruled out by VAR.
Jesus came off the bench and added more threat to City’s attack and but for an earlier offside in the move, almost claimed the winning goal.
“Always he is alert and he showed his quality but it was unlucky it was offside,” he said.
“I'm glad for him because he changed the game with his pace and his desire.”