The hosts drafted Joao Cancelo and Ilkay Gundogan back into the starting lineup and dominated most of the early proceedings.
Manchester City went ahead in the 19th minute when Riyad Mahrez intercepted a misplaced pass by Emre Can. The Algeria international quickly fed Kevin de Bruyne, who launched a devastating counterattack.
His pristine through-ball back to Mahrez found him down the left channel. The former Leicester City man showed great awareness to cut back for De Bruyne to place into the net.
They had a chance to double their lead when referee Ovidiu Hategan pointed to the spot after Can seemingly brought down Rodri in the area. However, the referee changed his decision after his VAR review deemed the contact not strong enough to warrant a theatrical fall.
Borussia Dortmund had the ball in the back of the net in the 37th minute after Jude Bellingham dispossessed Ederson outside his area. However, the referee expunged the goal for a foul, much to the chagrin of the visitors.
The second half started with Dortmund on the front foot. They got their first real chance of the game when Erling Haaland showed great strength to hold off Ruben Dias after being played through by Mahmoud Dahoud.
Ederson, however, produced a save with his leg to deny the Norwegian the equalizer.
This jolted Manchester City back to life. They started dominating proceedings once again, with Marwin Hitz having to pull off a stunning save at point-blank range from Phil Foden.
Kevin de Bruyne was also close to scoring after he dribbled across the Dortmund backline but saw his shot sail just wide.
The hosts paid the price for failing to take their chances when Marco Reus drew Dortmund level in the 84th minute after being set up by Erling Haaland. The goal saw Reus become BVB's all-time highest goalscorer in the UEFA Champions League.
Just when it seemed like both sides would share the spoils, Kevin de Bruyne's pristine cross to the backpost found Ilkay Gundogan, who set Foden up to score the winner.
There were appeals from the visitors that the Germany international was offside, but replays showed he timed his run to perfection to give Manchester City the lead.
Both sides will turn their attention to domestic action this weekend ahead of the return leg in Germany next week.
Here are five talking points from the fixture.
#5 Exciting fixture leaves everything to play for in the second leg
Manchester City dominated most of the proceedings from start to finish. Having gotten an early lead, it seemed like they were going to blow Dortmund away.
However, a lackluster display in attack meant that they failed to kill the game off, which gave the visitors hope of getting back into it. That was precisely what happened when Reus leveled matters with six minutes to go.
Despite Foden's late winner, Dortmund's away goal gave them a lifeline heading into the second leg on home turf.
Considering Manchester City's recent malaise at this stage of the tournament, Pep Guardiola will be ruing his side's inability to make the most of their dominance.
#4 Did Erling Haaland do enough in front of potential employers Manchester City?
Erling Haaland is unarguably the hottest property in world football right now. With several European elites having gone head-to-head for his signature in 2019, another battle is set to ensue in the summer.
The 20-year-old has been immaculate since joining Borussia Dortmund, and it is an open secret that a move to a bigger club is on the cards in the near future.
Manchester City are one of the sides touted to be interested in the Norway international, and their need for a central striker has been bolstered by the impending departure of Sergio Aguero.
The fixture at the Etihad offered Haaland the chance to show what he is capable of up close. However, with the hosts dominating proceedings for most of the game, he was left feeding off scraps.
The one true opportunity that fell in the way of the former Salzburg man saw him showcase the full range of his abilities. He timed his run to perfection and also showed great strength to hold off the challenge of Ruben Dias.
Only a last-ditch save from Ederson prevented Haaland from equalizing at the start of the second half.
He, however, came to the fore late on when he set up Reus for the equalizer. Despite not getting on the scoresheet himself, Haaland still showed his versatility against Manchester City.