The short answer is that Meyers does consider const_iterators preferable when using an up-to-date implementation of the STL due to improvements made in the C++11 standard.
Before discussing his reasons for giving the anti-const_iterator advice in the first place and explaining what changed, though, I need to clear up a misconception. You write:
isn't that the whole point of a const_iterator, that it does not allow modifying the container?
This is a sensible assumption, but in fact this is not quite the purpose of const_iterator. As Meyers explains in the third edition of Effective C++ (written, notably, before C++11):
Declaring an iterator const is like declaring a pointer const (i.e., declaring a T* const pointer): the iterator isn't allowed to point to something different, but the thing it points to may be modified. If you want an iterator that points to something that can't be modified (i.e., the STL analogue of a const T* pointer), you want a const_iterator[.]
In short, const_iterator doesn't protect against modifying the container, it protects against modifying the contained values. This is why Meyers expects insertto be compatible with const_iterator: it doesn't modify any of the elements already present in the container.
erase is a bit stranger, because it causes a contained element to be destroyed, which is a non-const operation. But note that the element's destructor is not called via the iterator itself; the iterator is merely the means the API provides to specify the item to be erased. Semantically, a const_iterator should be able to serve this purpose as well as an an iterator.
Now, as for the advice in Effective STL and its subsequent retraction, I'll paraphrase and quote some of Effective Modern C++ on the matter. In Item 13, "Prefer const_iterators to iterators", Meyers writes:
...in C++98, const_iterators had only halfhearted support. It wasn't that easy to create them, and once you had one, the ways you could use it were limited....
...there was no simple way to get a const_iterator from a non-const container...
Once you had the const_iterators...locations for insertions (and erasures) could be specified only by iterators. const_iterators weren't acceptable.
He gives an example making extensive use of static_cast to get around these limitations, but points out,
...the code I've shown might not compile, either, because there's no portable conversion from a const_iterator to an iterator, not even with a static_cast. Even the semantic sledgehammer known as reinterpret_cast can't do the job.
He summarizes:
...const_iterators were so much trouble in C++98, they were rarely worth the bother.
These issues were addressed by the C++11 standard. As alluded to in a comment on your question, this standard introduced cbegin and cend, which return const_iterator regardless of whether the container itself is const. Also, insert and erase were given overloads taking const_iterator. This makes const_iterator much easier to use.