The recommended approach is to create a user-defined network where you can connect multiple containers.
The network can easily be created using the following command:
docker network create -d bridge my-net
When the network has been created you can start containers like this.
First container:
docker run -it --name b1 --network=my-net --rm bash:4.4
Second container:
docker run -it --name b2 --network=my-net --rm bash:4.4
bash-4.4# ping b1
PING b2 (172.26.0.3): 56 data bytes
64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.111 ms
64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.336 ms
...
More info can be found in the Docker docs about user-defined networks.
Another possible approach that does not use linking is to map the containers by exposing a port on each container and binding the containers to the host interface.
docker run --net=host -p 127.0.0.1:5555:5555 --name container1 my/dockerimage1
docker run --net=host -p 127.0.0.1:6666:6666 --name container2 my/dockerimage2
This way container1 can access container2 via localhost:6666 and container2 can access container1 via localhost:5555.
This is not linking but there is no way to do bidirectional linking.
The documentation for docker networking explains this further.