Pep Guardiola’s side had an incredible 29 shots but a combination of missed opportunities, brilliant goalkeeping and brave defending kept the game in the balance until the dying minutes.
The Hammers went into the game unbeaten and, despite sitting back for large parts of the game, they offered plenty of threat and went in at half-time ahead thanks to James Ward-Prowse’s diving header after a quick break.
But Doku’s solo effort pulled City level inside 60 seconds of the restart and Bernardo Silva finally put us ahead with quarter of an hour remaining.
Haaland went close on several occasions and finally got his goal in the final minutes to clinch our fifth win in five Premier League games.
City pushed the Hammers back from the opening stages with Doku looking lively down the left-hand side and Haaland and Foden linking up neatly from the off.
The home side somehow survived going behind in just the sixth minute with City firing in four attempts in quick succession.
From Foden’s corner, Rodrigo’s header was superbly saved by Alphonse Areola, his rebound effort was blocked and a third attempt was stopped on the line by Tomas Soucek before Ruben Dias’ follow-up header was tipped cleared again by the West Ham keeper.
New boys Doku and Josko Gvardiol then combined to set up a chance for Haaland at the back post but he couldn’t squeeze the ball on target.
West Ham looked to threaten from dead-ball situations with the expert delivery of summer signing Ward-Prowse. But from a 15th minute corner, Jarrod Bowen’s centre was flicked on by Soucek for Nayef Aguerd who could only head his close-range effort wide.
But it was Ward-Prowse himself who was on the end of a cross when he gave the Hammers a lead by escaping the marking to head home after Soucek pounced on a loose touch from Doku to start a lightning counter-attack that saw him send over a perfect centre.
It was a sucker-punch for Pep Guardiola’s side who had dominated possession on the edge of West Ham’s box for the majority of the first half and patiently tried to carve out an opportunity.
Going behind didn’t alter the dynamic of the game and Doku created another huge chance with clever wing play to fire over a low cross to pick out Haaland at the backpost but his effort was scrambled off the line by Aguerd.
First half frustrations were forgotten inside 60 seconds after the restart when Doku equalised with his first goal for City. An excellent run saw the Hammers’ defenders backing off from a challenge and he curled a delightful strike inside the far post.
Foden went close with a flicked header and Alvarez smacked the inside of the post with a 25-yard free-kick and a spectacular Haaland volley was denied by Areola as City chased a second.
But West Ham, full of confidence on the back of three successive wins, had their own threat and Ederson made two wonderful saves to keep them out, smothering a break from Antonio and diving full-length to turn away Kurt Zouma’s header.
Matheus Nunes came on midway through the second half to make his debut and he had a hand in setting up the winner with a dash into the box.
The ball dropped to Alvarez on the edge of the area who delicately scooped the ball over the Hammers' defence for Bernardo to loop in a finish with Haaland deciding against touching it in, in case he was offside.
MAN OF THE MATCH
In just his second game since his summer switch from Stade Rennais, Doku showed why so many experts have identified him as an exciting talent.
The Belgian winger was a threat from the opening minutes as he took the game to the hosts, constantly asking questions of the defenders with his pace and quick feet.
A couple of magic moments carved out first half opportunities, although a miscontrol in front of Guardiola was punished by West Ham as they broke for the opening goal.
But it was unfortunate after an impressive opening 45 minutes that was set to get even better after the restart.
As Hammers' defenders backed away, he stroked home a delightful leveller and celebrated with a 'Griddy' in front of the joyous away fans.
Doku continued to terrorise the Hammers' defence and drew a number of 'tactical' fouls in an attempt to stop him.
NEVER GONNA GIVE YOU UP
City's victory was borne out of a will to win that has underpinned our success in recent years.
Under David Moyes, the Hammers have become masters at soaking up pressure and catching out teams on the break, helping them to Europa Conference League success last season and an unbeaten run in four games this term.
It was the gameplan again and sides could easily become frustrated, particularly when the remarkable pinball of shots somehow stayed out in the opening five minutes.
But we kept our patience and relentlessly kept creating chance after chance to get us over the line and our summer signings were an integral part of the success, with a quick lesson in what is required in the punishing Premier League.
HOW WE LINED UP
Guardiola was back on the touchline after missing the matches before the international break following surgery and he made just two changes to the starting line-up from the side that beat Fulham 5-1.
It was a familiar 4-3-3 formation with Doku starting on the left and Foden on the right with Alvarez playing close to Haaland.
WEST HAM XI: Areola, Coufal (Kehrer 87), Zouma, Aguerd, Emerson, Alvarez (Benrahma 68), Ward-Prowse, Soucek (Ings 87), Paqueta, Bowen, Antonio (Kudus 67).
Subs: Fabianski, Cresswell, Fornals, Mavropanos, Ogbonna.
Subs: Ortega Moreno, Carson, Phillips.
What it means
City remain two points clear at the top of the Premier League table with five wins from our opening five games in 2023/24.
We are the only side to maintain a 100% record in the English top flight this season as we chase a fourth successive title.
We begin the defence of the Champions League with a home game against Serbian champions Red Star Belgrade on Tuesday at 20:00 (UK).
Our next game in the Premier League is also at the Etihad Stadium with Nottingham Forest the visitors on Saturday 23 September at 15:00 (UK).
"We made so many chances in 90 minutes against a team that sits so deep – I’m so incredibly proud of my team.
"It’s a great win for us with all the injury problems we have within our squad.
"We spoke at half-time because we were really, really good in the first half and in the second at times we were lucky and we had to be patient and wait for our chances, but it was really good the way we played."
"I think we reacted very well. We had a lot of chances in the first-half without scoring but we kept on going. They scored a goal, I had bad touch, so I was disappointed.
"We reacted well and kept on playing and after that we scored three goals and had a good game.
"I enjoyed it [against Vladimir Coufal]. I had a lot of one on ones, the coach knows i’m good at that."