The quadruple-chasing Premier League leaders had looked like they would have to settle for a draw at the Etihad Stadium when Marco Reus levelled for the German side six minutes from time at the Etihad Stadium.
But Foden, who had twice tested Dortmund keeper Marwin Hitz in the second half of a controversial encounter, hit back from close range as the clock ran down.
Having taken the lead through Kevin De Bruyne, City now have the edge heading into next week's second leg in Germany.
But, having failed at the last-eight stage in the last three seasons, Pep Guardiola's side will be well aware they still have work to do.
Dortmund will also leave Manchester with reason to feel aggrieved after having a Jude Bellingham goal controversially disallowed before half-time.
The visitors had come into the game amid an indifferent run of form and struggling to keep their hopes of Champions League qualification via the Bundesliga alive.
Yet even though their former City academy star Jadon Sancho was sat at home injured, they played with a determination not to allow the remainder of their season under interim manager Edin Terzic to drift away.
They played plenty of composed football and, although City kept the dangerous Erling Haaland relatively quiet, England international Bellingham was a constant threat.
Bellingham had the first serious opportunity of the night when he created space in the area but Ederson pushed away his left-foot strike.
City, again starting without a recognised centre-forward, took time to impose themselves but they were ruthless in pouncing on a mistake to snatch the lead after 19 minutes.
Former Liverpool midfielder Emre Can mishit a pass straight to Riyad Mahrez and the Algerian quickly launched a counter-attack by releasing De Bruyne.
Foden then whipped in a low ball from the left and Mahrez's cut-back from the byline was tapped in at close range by De Bruyne.
Despite going ahead, City did not look comfortable. Some sloppy play on the edge of their own box almost allowed in Reus but Ederson blocked.
City were given a penalty in strange circumstances on the half-hour after Rodri went down clutching his face following a challenge with Can. Yet it was not clear whether contact had been made and, after being asked to check the monitor by the VAR, referee Ovidiu Hategan eventually reversed his decision.
Further controversy involving the Romanian official soon followed as he bizarrely disallowed a Bellingham equaliser.
Bellingham had closed down Ederson as he attempted a clearance and ended up taking the ball and tapping home as the Brazilian missed his kick. Any contact was Ederson catching Bellingham in his failed attempt to clear but Hategan gave a foul against Dortmund.
"This Ref needs checking!" the watching Sancho tweeted.
Haaland finally got chance to show his pace early in the second half as he outsprinted Ruben Dias to get in on goal but Ederson was alert to the danger.
City picked up the pace and went close on the hour when De Bruyne found Foden in front of goal but goalkeeper Hitz blocked his first-time shot.
Hitz saved again from the same player soon after and De Bruyne shrugged off a challenge before firing narrowly wide.
City looked set to rue those misses as Dortmund claimed a well-worked equaliser six minutes from time.
Haaland was involved, cleverly flicking the ball into the path of Reus who broke into the area to clip over Ederson.
That sparked City into action again and they reclaimed the lead in the final minute as Foden turned in from close range.