Bottas led from pole and was running in the de facto race lead, behind the long-running Max Verstappen, when he was told to let Hamilton past to protect him from Vettel.
Hamilton’s eighth victory of the season means his lead over Vettel is now 50 points with five races to go and 125 points up for grabs after Bottas, who sacrificed a first win of 2018 for his teammate, restricted the Ferrari driver to third.
Bottas held his lead at the start as a good Vettel launch allowed him to attack Hamilton through the Turn 1 kink, but Hamilton regrouped in Bottas’s slipstream and rebuffed the Ferrari.
Hamilton had such a good run behind his teammate that he closed right up and locked up slightly under braking for Turn 2, which allowed Vettel to attack again through the ensuing long left-hander, but Hamilton held the place.
Bottas led until pitting on lap 12, with Vettel stopping on the next lap and Mercedes keeping Hamilton out another lap longer.
Mercedes told Bottas to slow down and back Vettel up, but it was not enough to prevent Vettel undercutting Hamilton and stealing second.
Hamilton moved quickly to respond and was in Vettel’s slipstream two laps later on the run Turn 2 but Vettel appeared to move to the right twice in the process.
Hamilton retaliated with a good run out of the corner and toughed it out on the outside through the long left-hand Turn 3 and nailed Vettel on the inside of Turn 4.
Hamilton caught and followed Bottas for several laps but started to develop a blister on his left-rear tyre, not helped by Bottas being backed up by the long-running Verstappen.
Mercedes acted on lap 25, telling Bottas to slow and let Hamilton by at Turn 13, which he did.
Hamilton moved into second but did not start attacking Verstappen, which frustrated Bottas and led Mercedes strategist James Vowles to tell Bottas over the radio that he understood his concerns but had to make the team orders decision to secure Hamilton’s position.
Verstappen continued to lead with relative comfort and extended a stunning first stint in which he rose from 19th to fifth in just seven laps.
Hamilton reported engine “hesitations” but as those concerns appeared to ease he attacked Verstappen on lap 42 but had the door slammed in his face.
Verstappen finally stopped a lap later, releasing the Mercedes pair with 10 laps to go to ease clear to a comfortable one-two – Bottas asked how they would finish the race, indicating he wanted to be let back ahead, but was told they would maintain position.
Kimi Raikkonen was a muted fourth after Verstappen lacked the pace on fresh ultrasofts to mount a challenge in the closing stages.
Daniel Ricciardo made it back to sixth in the second Red Bull, having been passed by Verstappen at the start and failing to replicate the speed of his teammate’s early charge.
Charles Leclerc produced a fine drive to take seventh, having ran as high as fifth early on, and claimed his first unofficial ‘Class B’ win of the season for Sauber.
Kevin Magnussen claimed eighth for Haas after fending off the Racing Point Force Indias for the duration of the race, including an on-the-limit defence against Esteban Ocon early on.
Ocon finished ninth ahead of Sergio Perez having briefly led Perez ahead to try, unsuccessful, to pass the Haas.
The race featured only two retirements.
Toro Rosso teammates Pierre Gasly and Brendon Hartley suffered independent spins almost simultaneously but made it back to the pits to retire their cars having suffered brake failures.
The causes was not immediately determined but Toro Rosso had changed the rear brake duct blanking before the start.