Supporters of the move, which passed by a 303-9 vote, said it was justified by Russian aggression toward Ukraine, including the annexation of its Crimean Peninsula in March and Russian support for a separatist insurgency in eastern Ukraine, where some 4,700 people have been killed since the spring.
But opponents said it will only increase tensions, and Moscow echoed that view.
"This is counterproductive, it only heats up the confrontation, creating the illusion that accepting such a law is the road to regulating the deep internal crisis in Ukraine," said Russian Foreign Minister Sergey Lavrov.
Russia routinely characterizes the Ukrainian crisis as an internal matter and rejects claims from Ukraine and the West that it has sent troops and equipment to eastern Ukraine and shelled the region from Russian border areas.
Although Ukraine had pursued NATO membership several years ago, it declared itself a non-bloc country after Russia-friendly Viktor Yanukovych became president in 2010. Yanukovych fled the country in February after months of street protests that exploded into violence, and was replaced by Western-leaning Petro Poroshenko in May.
Russia's annexation of the Crimean Peninsula and its support for the separatist insurgency appear partly rooted in fears that the Western military alliance could expand its presence on the Russian border. Current NATO members Estonia, Latvia, Lithuania and Poland all border Russia
The vote does not mean that Ukraine will apply to join NATO. But "in the conditions of the current aggression against Ukraine, this law opens for us new mechanisms," Ukrainian Foreign Minister Pavlo Klimkin told the parliament.
However, Ukraine's prospects for NATO membership in the near term appear dim. With its long-underfunded military suffering from the war with the separatists and the country's economy in peril, Ukraine has much to overcome to achieve the stability that the alliance seeks in members.