The Briton's lead over Bottas shrunk to a still healthy 44 points after 10 of 17 races, with the Finn collecting a bonus point for fastest lap.
"Never give up. It's a good day," said Bottas, who addressed his critics in more basic terms over the team radio as he took the chequered flag.
"It's nice to get a win, it's been a while and I need to try and keep the momentum...there's still quite a few races to go, so you never know. I'll keep pushing, I won't give up and we'll see how it ends up."
The win -- by 7.729 seconds -- was the Finn's second of the season, and first since the Austrian opener in July.
Bottas said he had been lucky but he might have won anyway, with Hamilton starting on the higher-wearing softs after a fraught Saturday qualifying while the Finn was on the mediums -- the better long-term strategy.
Hamilton's hopes were in any case dashed when stewards issued two five-second penalties for making practice starts outside the designated area as he headed to the grid.
"I'm pretty sure no-one's got two five second penalties for something so ridiculous before," said the Briton, who had won six of the nine races before Sochi and had been authorised by the team to practise a start.
"I didn't put anyone in danger. I've done this at a million tracks over the years and never been questioned on it.
Hamilton also collected two penalty points on his licence, leaving him just two away from a one-race ban triggered if a driver gets 12 in a 12-month period.
In a dull race after two exciting rounds in Italy, with lonely races for the top three, Mercedes continued their record of winning every Russian Grand Prix since the first held on the streets around the 2014 Winter Olympics venue.
Mexican Sergio Perez was fourth for Racing Point with Australian Daniel Ricciardo fifth for Renault and Charles Leclerc sixth for Ferrari.
Frenchman Esteban Ocon took seventh for Renault with Russian driver Daniil Kvyat eighth and pleasing the first real crowd of the season after the first eight races were held behind closed doors due to the COVID-19 pandemic.
AlphaTauri team mate Pierre Gasly, a surprise winner at Monza, was ninth and Red Bull's Alexander Albon took the final point in 10th.
The safety car was deployed for four laps after the start when McLaren's Carlos Sainz went off and misjudged his return to the track, hitting the wall hard.
Leclerc also tagged Lance Stroll's Racing Point, with the Canadian spinning out.
Hamilton served his two penalties at the same time, returning in 11th place but moving up to third after others pitted. "This is just ridiculous, man," he said over the radio.
(Reporting by Alan Baldwin in London, editing by Ed Osmond) ((email@example.com; +442075427933;))