Starting with Docker 1.9 we have a new feature that I find very useful and necessary - build arguments (see the docker build reference). But docker already has a similar concept - environment variables. So one might be confused (and I certainly was) about the relation of these two.
Actually they have lot in common. Idea for build arguments seems to be created by a several use cases that required passing environment variables to docker at build time. But docker team did not like that idea and decided to create a new concept instead and that is how build arguments were created.
So for me the main distinction between these two concepts are that build arguments are suitable for passing parameters to the dockerfile during a build time. On the other hand, environment variables are something, that you will probably use mainly during runtime (although there are some exceptions but let’s not get into that right now). Another valid use case for environment variables is declaring them inside the Dockerfile. If done like that, all Dockerfiles inheriting from yours can access that value. But there is no way how to change that value during a build time.