Championship leader Hamilton, who was targeting a record-equalling 91st Formula One victory in Sochi, made two practice starts outside the designated area in the pit lane before taking his place for the start of the race.
The stewards handed him two five-second penalties on safety grounds for the errors, effectively wiping him out of victory contention.
Hamilton was already starting the race on the back foot. A sketchy run in qualifying before storming to pole meant he had to start on the soft tyre, which forced him into an early pit stop, paving the way for Bottas to battle Red Bull Racing’s Max Verstappen for the lead.
Bottas, starting third, seized the upper hand in that battle early by picking up Hamilton’s slipstream off the line to cruise past Verstappen into second. He would have taken the lead too, he said, had a “massive bee” not struck his visor in the braking zone, throwing him off.
The race was placed under safety car before the end of the first lap to clear up two crashes - Carlos Sainz had smacked into the wall trying to rejoin the track after running wide at turn two, while Lance Stroll was spun around by Charles Leclerc at turn four - and at the restart Hamilton led Bottas and Verstappen at the front.
But his lead was always going to be short-lived. He stopped on lap 16 to serve his 10-second penalty and make his sole tyre change, dropping to 11th and an insurmountable 35 seconds off the lead.
Bottas was left to inherit first place, and it was immediately clear his Mercedes had the pace to beat Verstappen. Easily covering the Dutchman at the pit stops just before mid-distance, he cruised home to a comfortable seven-second victory, his second of the season.
“It’s nice to get a win, it’s been a while,” he said. “Once I was in clear air I felt the pace was pretty awesome and I could control everything.”
Taking an extra point for fastest lap, the Finn’s championship deficit to Hamilton shrunk to 44 points with seven rounds remaining.
“I definitely need to try and keep the momentum,” he said. “You just never know. I’ll keep pushing and never give up.”
Verstappen was happy to finish second, the maximum available to Red Bull Racing.
“I was just trying to do my own race,” he said. “They were fast today.
“I think we managed it well. I did everything I could.”
Hamilton managed to rise to third, benefitting from the midfield making later pit stops but hamstrung by having to manage a long final stint on a single set of tyres.
Clearly feeling wronged by his costly double penalty, the Briton cut a despondent figure out of the car.
“It is what it is,” he said. “It’s done now. I’ll take the points I got and move on.”
Sergio Perez finished where he started in fourth for Racing Point ahead of Renault’s Daniel Ricciardo.
Charles Leclerc was a superb sixth, benefitting in part from teammate Sebastian Vettel delaying his first stop to slow Renault’s Esteban Ocon, who finished seventh.
Daniil Kvyat raced Ocon for the place right to the chequered flag but fell short, leaving him eighth ahead of teammate Pierre Gasly, who passed two cars in the final eight laps to finish ninth.
Thai driver Alex Albon scored the final point in 10th for Red Bull Racing after starting 15th on the grid with a gearbox penalty.