With an EXISTS clause you select all customers for which exist at least one order_details record.
SELECT * FROM customers c WHERE EXISTS (SELECT * FROM order_details od WHERE od.customer_id = c.customer_id);
With a join you'd select again those customers. However, you'd select each as often as there exists an order_detail for them. I.e. you'd have many duplicates.
SELECT c.* FROM customers c JOIN order_details od ON c.customer_id = od.customer_id;
You can remove the duplicates from your results with DISTINCT so as to get each customer only once again:
SELECT DISTINCT c.* FROM customers c JOIN order_details od ON c.customer_id = od.customer_id;
But why generate all the duplicates only to have to remove them again? Don't do this. Only join when you really want joined results.
Another option, which I consider even more readable than an EXISTS clause is the IN clause by the way. This would be my way of writing the query:
SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM order_details);