Solution 1:

You can use dd or fallocate (or head or a few other tools) to create a file to act as your container. Then as Vincent Yu stated cryptsetup can handle the loop setup/teardown for you.

fallocate -l 100M mypath/filecontainer
sudo losetup # Debug for demonstration, not necessary in a real script
sudo cryptsetup -y luksFormat mypath/filecontainer
sudo losetup # Debug for demonstration, not necessary in a real script
sudo cryptsetup luksOpen mypath/filecontainer filecontainer
sudo losetup # Debug for demonstration, not necessary in a real script
sudo mkfs -t ext4 /dev/mapper/filecontainer
sync
sudo cryptsetup luksClose filecontainer
sudo losetup # Debug for demonstration, not necessary in a real script

In the debug sudo losetup output, note the AUTOCLEAR = 1 for the filecontainer entry. You could instead go crazy with loopdev=$(sudo losetup -f); mount -o loop <etc>, but letting cryptsetup handle it is WAY nicer.

The key is you want to make sure you FIRST use cryptsetup luksOpen containerfile mappedname to have it mounted to /dev/mapper/mappedname by default (you can give it a full path starting with / and it will mount there instead I believe, and THEN format the /dev/mapper/mappedname target and makes sure you are NOT touching the filecontainer directly, otherwise you are bypassing the encryption engine and just creating an unencrypted loopback file.

Solution 2:

If you don't manage the loop device yourself, cryptsetup will automatically set up a loop device and close it when it is no longer needed. So there is no difference between the two; cryptsetup always works on the loop device. See man cryptsetup:

NOTES ON LOOPBACK DEVICE USE

Cryptsetup is usually used directly on a block device (disk partition or LVM volume). However, if the device argument is a file, cryptsetup tries to allocate a loopback device and map it into this file. This mode requires Linux kernel 2.6.25 or more recent which supports the loop autoclear flag (loop device is cleared on last close automatically). Of course, you can always map a file to a loop-device manually. See the cryptsetup FAQ for an example.

When device mapping is active, you can see the loop backing file in the status command output. Also see losetup(8).