The autoencoder which uses convolutional layers is essentially a subset of CNN architectures.
The idea of an encoder is exactly as you stated you want to go from a space $\mathbb{R}^n$ to $\mathbb{R}^m$ where $m<n$. There are a lot of ways to compress information in such a way and these techniques used to be called compressed sensing. The idea was then to find automated ways to generate this mapping from n-dimensions to m-dimensions. As the name suggests it is an autoencoder. Lately the most popular method for doing this is using a CNN let's just refer to this specific type of autoencoder as an autoencoder for simplicity, but remember there are other ways of doing this.
The autoencoder has a special structure where we will constrain the number of parameters at the center layer. The encoder is the part of the network which compresses the information into the m-dimensional space. We then use a decoder to reconstruct the input from the compressed data. An autoencoder is trained by feeding the same input and output. We want the network to recreate the input as closely as possible. If the output is equal to the input then we have perfect reconstruction and all the information contained in the input is contained. When we constrain the dimensions there will always be some information loss. We will want to minimize this loss.
Here is an example of a vanilla autoencoder
input_img = Input(shape=(28, 28, 1)) # adapt this if using `channels_first` image data format
x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
# at this point the representation is compressed
x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
What happens if the network just learn the identity function!!
For this problem the denoising autoencoder was conceived. Add white Gaussian noise to the input and train using the original image at the output. This forces the network to learn the underlining distribution of the images and not just copy them to the output. You can use the same network as above. The noise can be added as follows
noise_factor = 0.5
x_train_noisy = x_train_reshaped + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train_reshaped.shape)
x_test_noisy = x_test_reshaped + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test_reshaped.shape)
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)